Auto merge of #3154 - rust-lang:rustup-2023-11-04, r=RalfJung
Automatic Rustup
This commit is contained in:
commit
1b2e4a9c94
770 changed files with 7340 additions and 6547 deletions
3
.github/workflows/ci.yml
vendored
3
.github/workflows/ci.yml
vendored
|
@ -57,8 +57,9 @@ jobs:
|
|||
os: ubuntu-20.04-4core-16gb
|
||||
env: {}
|
||||
- name: x86_64-gnu-llvm-15
|
||||
env:
|
||||
ENABLE_GCC_CODEGEN: "1"
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
env: {}
|
||||
- name: x86_64-gnu-tools
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
env: {}
|
||||
|
|
36
Cargo.lock
36
Cargo.lock
|
@ -556,6 +556,7 @@ name = "clippy"
|
|||
version = "0.1.75"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"clippy_config",
|
||||
"clippy_lints",
|
||||
"clippy_utils",
|
||||
"color-print",
|
||||
|
@ -578,6 +579,16 @@ dependencies = [
|
|||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clippy_config"
|
||||
version = "0.1.75"
|
||||
dependencies = [
|
||||
"rustc-semver",
|
||||
"serde",
|
||||
"toml 0.7.5",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clippy_dev"
|
||||
version = "0.0.1"
|
||||
|
@ -597,6 +608,7 @@ version = "0.1.75"
|
|||
dependencies = [
|
||||
"arrayvec",
|
||||
"cargo_metadata 0.15.4",
|
||||
"clippy_config",
|
||||
"clippy_utils",
|
||||
"declare_clippy_lint",
|
||||
"if_chain",
|
||||
|
@ -621,10 +633,10 @@ name = "clippy_utils"
|
|||
version = "0.1.75"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"clippy_config",
|
||||
"if_chain",
|
||||
"itertools",
|
||||
"rustc-semver",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2465,9 +2477,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "minifier"
|
||||
version = "0.2.3"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5394aa376422b4b2b6c02fd9cfcb657e4ec544ae98e43d7d5d785fd0d042fd6d"
|
||||
checksum = "95bbbf96b9ac3482c2a25450b67a15ed851319bc5fabf3b40742ea9066e84282"
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
|
@ -3512,7 +3524,6 @@ dependencies = [
|
|||
"rustc_span",
|
||||
"rustc_target",
|
||||
"thin-vec",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3785,7 +3796,6 @@ dependencies = [
|
|||
"rustc_monomorphize",
|
||||
"rustc_parse",
|
||||
"rustc_passes",
|
||||
"rustc_plugin_impl",
|
||||
"rustc_privacy",
|
||||
"rustc_query_system",
|
||||
"rustc_resolve",
|
||||
|
@ -4074,7 +4084,6 @@ dependencies = [
|
|||
"rustc_monomorphize",
|
||||
"rustc_parse",
|
||||
"rustc_passes",
|
||||
"rustc_plugin_impl",
|
||||
"rustc_privacy",
|
||||
"rustc_query_impl",
|
||||
"rustc_query_system",
|
||||
|
@ -4384,21 +4393,6 @@ dependencies = [
|
|||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_plugin_impl"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"libloading 0.7.4",
|
||||
"rustc_ast",
|
||||
"rustc_errors",
|
||||
"rustc_fluent_macro",
|
||||
"rustc_lint",
|
||||
"rustc_macros",
|
||||
"rustc_metadata",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_privacy"
|
||||
version = "0.0.0"
|
||||
|
|
|
@ -15,9 +15,10 @@ use rustc_hir as hir;
|
|||
use rustc_hir::def::Res;
|
||||
use rustc_hir::definitions::DefPathData;
|
||||
use rustc_session::errors::report_lit_error;
|
||||
use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
|
||||
use rustc_span::source_map::{respan, Spanned};
|
||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use rustc_span::{DesugaringKind, Span};
|
||||
use thin_vec::{thin_vec, ThinVec};
|
||||
|
||||
impl<'hir> LoweringContext<'_, 'hir> {
|
||||
|
|
|
@ -16,9 +16,8 @@ use rustc_hir::PredicateOrigin;
|
|||
use rustc_index::{Idx, IndexSlice, IndexVec};
|
||||
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
|
||||
use rustc_span::edit_distance::find_best_match_for_name;
|
||||
use rustc_span::source_map::DesugaringKind;
|
||||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_span::{DesugaringKind, Span, Symbol};
|
||||
use rustc_target::spec::abi;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use thin_vec::ThinVec;
|
||||
|
|
|
@ -71,9 +71,8 @@ use rustc_middle::{
|
|||
};
|
||||
use rustc_session::parse::{add_feature_diagnostics, feature_err};
|
||||
use rustc_span::hygiene::MacroKind;
|
||||
use rustc_span::source_map::DesugaringKind;
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_span::{DesugaringKind, Span, DUMMY_SP};
|
||||
use smallvec::SmallVec;
|
||||
use std::collections::hash_map::Entry;
|
||||
use thin_vec::ThinVec;
|
||||
|
|
|
@ -19,5 +19,4 @@ rustc_session = { path = "../rustc_session" }
|
|||
rustc_span = { path = "../rustc_span" }
|
||||
rustc_target = { path = "../rustc_target" }
|
||||
thin-vec = "0.2.12"
|
||||
tracing = "0.1"
|
||||
# tidy-alphabetical-end
|
||||
|
|
|
@ -1442,62 +1442,54 @@ fn deny_equality_constraints(
|
|||
let mut err = errors::EqualityInWhere { span: predicate.span, assoc: None, assoc2: None };
|
||||
|
||||
// Given `<A as Foo>::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`.
|
||||
if let TyKind::Path(Some(qself), full_path) = &predicate.lhs_ty.kind {
|
||||
if let TyKind::Path(None, path) = &qself.ty.kind {
|
||||
match &path.segments[..] {
|
||||
[PathSegment { ident, args: None, .. }] => {
|
||||
for param in &generics.params {
|
||||
if param.ident == *ident {
|
||||
let param = ident;
|
||||
match &full_path.segments[qself.position..] {
|
||||
[PathSegment { ident, args, .. }] => {
|
||||
// Make a new `Path` from `foo::Bar` to `Foo<Bar = RhsTy>`.
|
||||
let mut assoc_path = full_path.clone();
|
||||
// Remove `Bar` from `Foo::Bar`.
|
||||
assoc_path.segments.pop();
|
||||
let len = assoc_path.segments.len() - 1;
|
||||
let gen_args = args.as_deref().cloned();
|
||||
// Build `<Bar = RhsTy>`.
|
||||
let arg = AngleBracketedArg::Constraint(AssocConstraint {
|
||||
id: rustc_ast::node_id::DUMMY_NODE_ID,
|
||||
ident: *ident,
|
||||
gen_args,
|
||||
kind: AssocConstraintKind::Equality {
|
||||
term: predicate.rhs_ty.clone().into(),
|
||||
},
|
||||
span: ident.span,
|
||||
});
|
||||
// Add `<Bar = RhsTy>` to `Foo`.
|
||||
match &mut assoc_path.segments[len].args {
|
||||
Some(args) => match args.deref_mut() {
|
||||
GenericArgs::Parenthesized(_) => continue,
|
||||
GenericArgs::AngleBracketed(args) => {
|
||||
args.args.push(arg);
|
||||
}
|
||||
},
|
||||
empty_args => {
|
||||
*empty_args = Some(
|
||||
AngleBracketedArgs {
|
||||
span: ident.span,
|
||||
args: thin_vec![arg],
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
}
|
||||
err.assoc = Some(errors::AssociatedSuggestion {
|
||||
span: predicate.span,
|
||||
ident: *ident,
|
||||
param: *param,
|
||||
path: pprust::path_to_string(&assoc_path),
|
||||
})
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
if let TyKind::Path(Some(qself), full_path) = &predicate.lhs_ty.kind
|
||||
&& let TyKind::Path(None, path) = &qself.ty.kind
|
||||
&& let [PathSegment { ident, args: None, .. }] = &path.segments[..]
|
||||
{
|
||||
for param in &generics.params {
|
||||
if param.ident == *ident
|
||||
&& let [PathSegment { ident, args, .. }] = &full_path.segments[qself.position..]
|
||||
{
|
||||
// Make a new `Path` from `foo::Bar` to `Foo<Bar = RhsTy>`.
|
||||
let mut assoc_path = full_path.clone();
|
||||
// Remove `Bar` from `Foo::Bar`.
|
||||
assoc_path.segments.pop();
|
||||
let len = assoc_path.segments.len() - 1;
|
||||
let gen_args = args.as_deref().cloned();
|
||||
// Build `<Bar = RhsTy>`.
|
||||
let arg = AngleBracketedArg::Constraint(AssocConstraint {
|
||||
id: rustc_ast::node_id::DUMMY_NODE_ID,
|
||||
ident: *ident,
|
||||
gen_args,
|
||||
kind: AssocConstraintKind::Equality {
|
||||
term: predicate.rhs_ty.clone().into(),
|
||||
},
|
||||
span: ident.span,
|
||||
});
|
||||
// Add `<Bar = RhsTy>` to `Foo`.
|
||||
match &mut assoc_path.segments[len].args {
|
||||
Some(args) => match args.deref_mut() {
|
||||
GenericArgs::Parenthesized(_) => continue,
|
||||
GenericArgs::AngleBracketed(args) => {
|
||||
args.args.push(arg);
|
||||
}
|
||||
},
|
||||
empty_args => {
|
||||
*empty_args = Some(
|
||||
AngleBracketedArgs {
|
||||
span: ident.span,
|
||||
args: thin_vec![arg],
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
err.assoc = Some(errors::AssociatedSuggestion {
|
||||
span: predicate.span,
|
||||
ident: *ident,
|
||||
param: param.ident,
|
||||
path: pprust::path_to_string(&assoc_path),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,53 +10,54 @@ use rustc_span::symbol::sym;
|
|||
use rustc_span::Span;
|
||||
use rustc_target::spec::abi;
|
||||
use thin_vec::ThinVec;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::errors;
|
||||
|
||||
macro_rules! gate_feature_fn {
|
||||
($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{
|
||||
let (visitor, has_feature, span, name, explain, help) =
|
||||
(&*$visitor, $has_feature, $span, $name, $explain, $help);
|
||||
let has_feature: bool = has_feature(visitor.features);
|
||||
debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
|
||||
if !has_feature && !span.allows_unstable($name) {
|
||||
feature_err(&visitor.sess.parse_sess, name, span, explain).help(help).emit();
|
||||
/// The common case.
|
||||
macro_rules! gate {
|
||||
($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
|
||||
if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
|
||||
feature_err(&$visitor.sess.parse_sess, sym::$feature, $span, $explain).emit();
|
||||
}
|
||||
}};
|
||||
($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
|
||||
let (visitor, has_feature, span, name, explain) =
|
||||
(&*$visitor, $has_feature, $span, $name, $explain);
|
||||
let has_feature: bool = has_feature(visitor.features);
|
||||
debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
|
||||
if !has_feature && !span.allows_unstable($name) {
|
||||
feature_err(&visitor.sess.parse_sess, name, span, explain).emit();
|
||||
}
|
||||
}};
|
||||
(future_incompatible; $visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
|
||||
let (visitor, has_feature, span, name, explain) =
|
||||
(&*$visitor, $has_feature, $span, $name, $explain);
|
||||
let has_feature: bool = has_feature(visitor.features);
|
||||
debug!(
|
||||
"gate_feature(feature = {:?}, span = {:?}); has? {} (future_incompatible)",
|
||||
name, span, has_feature
|
||||
);
|
||||
if !has_feature && !span.allows_unstable($name) {
|
||||
feature_warn(&visitor.sess.parse_sess, name, span, explain);
|
||||
($visitor:expr, $feature:ident, $span:expr, $explain:expr, $help:expr) => {{
|
||||
if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
|
||||
feature_err(&$visitor.sess.parse_sess, sym::$feature, $span, $explain)
|
||||
.help($help)
|
||||
.emit();
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! gate_feature_post {
|
||||
($visitor: expr, $feature: ident, $span: expr, $explain: expr, $help: expr) => {
|
||||
gate_feature_fn!($visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain, $help)
|
||||
};
|
||||
($visitor: expr, $feature: ident, $span: expr, $explain: expr) => {
|
||||
gate_feature_fn!($visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain)
|
||||
};
|
||||
(future_incompatible; $visitor: expr, $feature: ident, $span: expr, $explain: expr) => {
|
||||
gate_feature_fn!(future_incompatible; $visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain)
|
||||
};
|
||||
/// The unusual case, where the `has_feature` condition is non-standard.
|
||||
macro_rules! gate_alt {
|
||||
($visitor:expr, $has_feature:expr, $name:expr, $span:expr, $explain:expr) => {{
|
||||
if !$has_feature && !$span.allows_unstable($name) {
|
||||
feature_err(&$visitor.sess.parse_sess, $name, $span, $explain).emit();
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
/// The case involving a multispan.
|
||||
macro_rules! gate_multi {
|
||||
($visitor:expr, $feature:ident, $spans:expr, $explain:expr) => {{
|
||||
if !$visitor.features.$feature {
|
||||
let spans: Vec<_> =
|
||||
$spans.filter(|span| !span.allows_unstable(sym::$feature)).collect();
|
||||
if !spans.is_empty() {
|
||||
feature_err(&$visitor.sess.parse_sess, sym::$feature, spans, $explain).emit();
|
||||
}
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
/// The legacy case.
|
||||
macro_rules! gate_legacy {
|
||||
($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
|
||||
if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
|
||||
feature_warn(&$visitor.sess.parse_sess, sym::$feature, $span, $explain);
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
pub fn check_attribute(attr: &ast::Attribute, sess: &Session, features: &Features) {
|
||||
|
@ -78,7 +79,7 @@ impl<'a> PostExpansionVisitor<'a> {
|
|||
match symbol_unescaped {
|
||||
// Stable
|
||||
sym::Rust | sym::C => {}
|
||||
abi => gate_feature_post!(
|
||||
abi => gate!(
|
||||
&self,
|
||||
const_extern_fn,
|
||||
span,
|
||||
|
@ -129,14 +130,14 @@ impl<'a> PostExpansionVisitor<'a> {
|
|||
fn visit_ty(&mut self, ty: &ast::Ty) {
|
||||
if let ast::TyKind::ImplTrait(..) = ty.kind {
|
||||
if self.in_associated_ty {
|
||||
gate_feature_post!(
|
||||
gate!(
|
||||
&self.vis,
|
||||
impl_trait_in_assoc_type,
|
||||
ty.span,
|
||||
"`impl Trait` in associated types is unstable"
|
||||
);
|
||||
} else {
|
||||
gate_feature_post!(
|
||||
gate!(
|
||||
&self.vis,
|
||||
type_alias_impl_trait,
|
||||
ty.span,
|
||||
|
@ -153,23 +154,16 @@ impl<'a> PostExpansionVisitor<'a> {
|
|||
fn check_late_bound_lifetime_defs(&self, params: &[ast::GenericParam]) {
|
||||
// Check only lifetime parameters are present and that the lifetime
|
||||
// parameters that are present have no bounds.
|
||||
let non_lt_param_spans: Vec<_> = params
|
||||
.iter()
|
||||
.filter_map(|param| match param.kind {
|
||||
ast::GenericParamKind::Lifetime { .. } => None,
|
||||
_ => Some(param.ident.span),
|
||||
})
|
||||
.collect();
|
||||
// FIXME: gate_feature_post doesn't really handle multispans...
|
||||
if !non_lt_param_spans.is_empty() && !self.features.non_lifetime_binders {
|
||||
feature_err(
|
||||
&self.sess.parse_sess,
|
||||
sym::non_lifetime_binders,
|
||||
non_lt_param_spans,
|
||||
crate::fluent_generated::ast_passes_forbidden_non_lifetime_param,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
let non_lt_param_spans = params.iter().filter_map(|param| match param.kind {
|
||||
ast::GenericParamKind::Lifetime { .. } => None,
|
||||
_ => Some(param.ident.span),
|
||||
});
|
||||
gate_multi!(
|
||||
&self,
|
||||
non_lifetime_binders,
|
||||
non_lt_param_spans,
|
||||
crate::fluent_generated::ast_passes_forbidden_non_lifetime_param
|
||||
);
|
||||
for param in params {
|
||||
if !param.bounds.is_empty() {
|
||||
let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
|
||||
|
@ -188,48 +182,39 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
..
|
||||
}) = attr_info
|
||||
{
|
||||
gate_feature_fn!(self, has_feature, attr.span, *name, *descr);
|
||||
gate_alt!(self, has_feature(&self.features), *name, attr.span, *descr);
|
||||
}
|
||||
// Check unstable flavors of the `#[doc]` attribute.
|
||||
if attr.has_name(sym::doc) {
|
||||
for nested_meta in attr.meta_item_list().unwrap_or_default() {
|
||||
macro_rules! gate_doc { ($($name:ident => $feature:ident)*) => {
|
||||
$(if nested_meta.has_name(sym::$name) {
|
||||
let msg = concat!("`#[doc(", stringify!($name), ")]` is experimental");
|
||||
gate_feature_post!(self, $feature, attr.span, msg);
|
||||
})*
|
||||
macro_rules! gate_doc { ($($s:literal { $($name:ident => $feature:ident)* })*) => {
|
||||
$($(if nested_meta.has_name(sym::$name) {
|
||||
let msg = concat!("`#[doc(", stringify!($name), ")]` is ", $s);
|
||||
gate!(self, $feature, attr.span, msg);
|
||||
})*)*
|
||||
}}
|
||||
|
||||
gate_doc!(
|
||||
cfg => doc_cfg
|
||||
cfg_hide => doc_cfg_hide
|
||||
masked => doc_masked
|
||||
notable_trait => doc_notable_trait
|
||||
"experimental" {
|
||||
cfg => doc_cfg
|
||||
cfg_hide => doc_cfg_hide
|
||||
masked => doc_masked
|
||||
notable_trait => doc_notable_trait
|
||||
}
|
||||
"meant for internal use only" {
|
||||
keyword => rustdoc_internals
|
||||
fake_variadic => rustdoc_internals
|
||||
}
|
||||
);
|
||||
|
||||
if nested_meta.has_name(sym::keyword) {
|
||||
let msg = "`#[doc(keyword)]` is meant for internal use only";
|
||||
gate_feature_post!(self, rustdoc_internals, attr.span, msg);
|
||||
}
|
||||
|
||||
if nested_meta.has_name(sym::fake_variadic) {
|
||||
let msg = "`#[doc(fake_variadic)]` is meant for internal use only";
|
||||
gate_feature_post!(self, rustdoc_internals, attr.span, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
if !attr.is_doc_comment()
|
||||
&& attr.get_normal_item().path.segments.len() == 2
|
||||
&& attr.get_normal_item().path.segments[0].ident.name == sym::diagnostic
|
||||
&& let [seg, _] = attr.get_normal_item().path.segments.as_slice()
|
||||
&& seg.ident.name == sym::diagnostic
|
||||
&& !self.features.diagnostic_namespace
|
||||
{
|
||||
let msg = "`#[diagnostic]` attribute name space is experimental";
|
||||
gate_feature_post!(
|
||||
self,
|
||||
diagnostic_namespace,
|
||||
attr.get_normal_item().path.segments[0].ident.span,
|
||||
msg
|
||||
);
|
||||
gate!(self, diagnostic_namespace, seg.ident.span, msg);
|
||||
}
|
||||
|
||||
// Emit errors for non-staged-api crates.
|
||||
|
@ -255,12 +240,11 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
|
||||
ast::ItemKind::Fn(..) => {
|
||||
if attr::contains_name(&i.attrs, sym::start) {
|
||||
gate_feature_post!(
|
||||
gate!(
|
||||
&self,
|
||||
start,
|
||||
i.span,
|
||||
"`#[start]` functions are experimental \
|
||||
and their signature may change \
|
||||
"`#[start]` functions are experimental and their signature may change \
|
||||
over time"
|
||||
);
|
||||
}
|
||||
|
@ -270,7 +254,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
for attr in attr::filter_by_name(&i.attrs, sym::repr) {
|
||||
for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) {
|
||||
if item.has_name(sym::simd) {
|
||||
gate_feature_post!(
|
||||
gate!(
|
||||
&self,
|
||||
repr_simd,
|
||||
attr.span,
|
||||
|
@ -283,7 +267,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
|
||||
ast::ItemKind::Impl(box ast::Impl { polarity, defaultness, of_trait, .. }) => {
|
||||
if let &ast::ImplPolarity::Negative(span) = polarity {
|
||||
gate_feature_post!(
|
||||
gate!(
|
||||
&self,
|
||||
negative_impls,
|
||||
span.to(of_trait.as_ref().map_or(span, |t| t.path.span)),
|
||||
|
@ -293,12 +277,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
}
|
||||
|
||||
if let ast::Defaultness::Default(_) = defaultness {
|
||||
gate_feature_post!(&self, specialization, i.span, "specialization is unstable");
|
||||
gate!(&self, specialization, i.span, "specialization is unstable");
|
||||
}
|
||||
}
|
||||
|
||||
ast::ItemKind::Trait(box ast::Trait { is_auto: ast::IsAuto::Yes, .. }) => {
|
||||
gate_feature_post!(
|
||||
gate!(
|
||||
&self,
|
||||
auto_traits,
|
||||
i.span,
|
||||
|
@ -307,12 +291,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
}
|
||||
|
||||
ast::ItemKind::TraitAlias(..) => {
|
||||
gate_feature_post!(&self, trait_alias, i.span, "trait aliases are experimental");
|
||||
gate!(&self, trait_alias, i.span, "trait aliases are experimental");
|
||||
}
|
||||
|
||||
ast::ItemKind::MacroDef(ast::MacroDef { macro_rules: false, .. }) => {
|
||||
let msg = "`macro` is experimental";
|
||||
gate_feature_post!(&self, decl_macro, i.span, msg);
|
||||
gate!(&self, decl_macro, i.span, msg);
|
||||
}
|
||||
|
||||
ast::ItemKind::TyAlias(box ast::TyAlias { ty: Some(ty), .. }) => {
|
||||
|
@ -331,7 +315,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
let link_name = attr::first_attr_value_str_by_name(&i.attrs, sym::link_name);
|
||||
let links_to_llvm = link_name.is_some_and(|val| val.as_str().starts_with("llvm."));
|
||||
if links_to_llvm {
|
||||
gate_feature_post!(
|
||||
gate!(
|
||||
&self,
|
||||
link_llvm_intrinsics,
|
||||
i.span,
|
||||
|
@ -340,7 +324,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
}
|
||||
}
|
||||
ast::ForeignItemKind::TyAlias(..) => {
|
||||
gate_feature_post!(&self, extern_types, i.span, "extern types are experimental");
|
||||
gate!(&self, extern_types, i.span, "extern types are experimental");
|
||||
}
|
||||
ast::ForeignItemKind::MacCall(..) => {}
|
||||
}
|
||||
|
@ -356,7 +340,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
self.check_late_bound_lifetime_defs(&bare_fn_ty.generic_params);
|
||||
}
|
||||
ast::TyKind::Never => {
|
||||
gate_feature_post!(&self, never_type, ty.span, "the `!` type is experimental");
|
||||
gate!(&self, never_type, ty.span, "the `!` type is experimental");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -389,7 +373,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
fn visit_expr(&mut self, e: &'a ast::Expr) {
|
||||
match e.kind {
|
||||
ast::ExprKind::TryBlock(_) => {
|
||||
gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental");
|
||||
gate!(&self, try_blocks, e.span, "`try` expression is experimental");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -405,7 +389,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
_ => pat,
|
||||
};
|
||||
if let PatKind::Range(Some(_), None, Spanned { .. }) = inner_pat.kind {
|
||||
gate_feature_post!(
|
||||
gate!(
|
||||
&self,
|
||||
half_open_range_patterns_in_slices,
|
||||
pat.span,
|
||||
|
@ -415,15 +399,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
}
|
||||
}
|
||||
PatKind::Box(..) => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
box_patterns,
|
||||
pattern.span,
|
||||
"box pattern syntax is experimental"
|
||||
);
|
||||
gate!(&self, box_patterns, pattern.span, "box pattern syntax is experimental");
|
||||
}
|
||||
PatKind::Range(_, Some(_), Spanned { node: RangeEnd::Excluded, .. }) => {
|
||||
gate_feature_post!(
|
||||
gate!(
|
||||
&self,
|
||||
exclusive_range_pattern,
|
||||
pattern.span,
|
||||
|
@ -451,7 +430,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
}
|
||||
|
||||
if fn_kind.ctxt() != Some(FnCtxt::Foreign) && fn_kind.decl().c_variadic() {
|
||||
gate_feature_post!(&self, c_variadic, span, "C-variadic functions are unstable");
|
||||
gate!(&self, c_variadic, span, "C-variadic functions are unstable");
|
||||
}
|
||||
|
||||
visit::walk_fn(self, fn_kind)
|
||||
|
@ -463,14 +442,14 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
&& args.inputs.is_empty()
|
||||
&& matches!(args.output, ast::FnRetTy::Default(..))
|
||||
{
|
||||
gate_feature_post!(
|
||||
gate!(
|
||||
&self,
|
||||
return_type_notation,
|
||||
constraint.span,
|
||||
"return type notation is experimental"
|
||||
);
|
||||
} else {
|
||||
gate_feature_post!(
|
||||
gate!(
|
||||
&self,
|
||||
associated_type_bounds,
|
||||
constraint.span,
|
||||
|
@ -486,7 +465,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
ast::AssocItemKind::Fn(_) => true,
|
||||
ast::AssocItemKind::Type(box ast::TyAlias { ty, .. }) => {
|
||||
if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) {
|
||||
gate_feature_post!(
|
||||
gate!(
|
||||
&self,
|
||||
associated_type_defaults,
|
||||
i.span,
|
||||
|
@ -502,11 +481,11 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
};
|
||||
if let ast::Defaultness::Default(_) = i.kind.defaultness() {
|
||||
// Limit `min_specialization` to only specializing functions.
|
||||
gate_feature_fn!(
|
||||
gate_alt!(
|
||||
&self,
|
||||
|x: &Features| x.specialization || (is_fn && x.min_specialization),
|
||||
i.span,
|
||||
self.features.specialization || (is_fn && self.features.min_specialization),
|
||||
sym::specialization,
|
||||
i.span,
|
||||
"specialization is unstable"
|
||||
);
|
||||
}
|
||||
|
@ -521,17 +500,17 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||
|
||||
let spans = sess.parse_sess.gated_spans.spans.borrow();
|
||||
macro_rules! gate_all {
|
||||
($gate:ident, $msg:literal, $help:literal) => {
|
||||
if let Some(spans) = spans.get(&sym::$gate) {
|
||||
for span in spans {
|
||||
gate_feature_post!(&visitor, $gate, *span, $msg, $help);
|
||||
}
|
||||
}
|
||||
};
|
||||
($gate:ident, $msg:literal) => {
|
||||
if let Some(spans) = spans.get(&sym::$gate) {
|
||||
for span in spans {
|
||||
gate_feature_post!(&visitor, $gate, *span, $msg);
|
||||
gate!(&visitor, $gate, *span, $msg);
|
||||
}
|
||||
}
|
||||
};
|
||||
($gate:ident, $msg:literal, $help:literal) => {
|
||||
if let Some(spans) = spans.get(&sym::$gate) {
|
||||
for span in spans {
|
||||
gate!(&visitor, $gate, *span, $msg, $help);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -556,7 +535,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||
gate_all!(more_qualified_paths, "usage of qualified paths in this context is experimental");
|
||||
for &span in spans.get(&sym::yield_expr).iter().copied().flatten() {
|
||||
if !span.at_least_rust_2024() {
|
||||
gate_feature_post!(&visitor, coroutines, span, "yield syntax is experimental");
|
||||
gate!(&visitor, coroutines, span, "yield syntax is experimental");
|
||||
}
|
||||
}
|
||||
gate_all!(gen_blocks, "gen blocks are experimental");
|
||||
|
@ -590,7 +569,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||
macro_rules! gate_all_legacy_dont_use {
|
||||
($gate:ident, $msg:literal) => {
|
||||
for span in spans.get(&sym::$gate).unwrap_or(&vec![]) {
|
||||
gate_feature_post!(future_incompatible; &visitor, $gate, *span, $msg);
|
||||
gate_legacy!(&visitor, $gate, *span, $msg);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -9,9 +9,8 @@ use rustc_middle::{
|
|||
hir::place::PlaceBase,
|
||||
mir::{self, BindingForm, Local, LocalDecl, LocalInfo, LocalKind, Location},
|
||||
};
|
||||
use rustc_span::source_map::DesugaringKind;
|
||||
use rustc_span::symbol::{kw, Symbol};
|
||||
use rustc_span::{sym, BytePos, Span};
|
||||
use rustc_span::{sym, BytePos, DesugaringKind, Span};
|
||||
use rustc_target::abi::FieldIdx;
|
||||
|
||||
use crate::diagnostics::BorrowedContentSource;
|
||||
|
|
|
@ -6,8 +6,8 @@ use crate::Upvar;
|
|||
use rustc_index::IndexSlice;
|
||||
use rustc_middle::mir::{Body, Local};
|
||||
use rustc_middle::ty::{RegionVid, TyCtxt};
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::Span;
|
||||
|
||||
impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
pub(crate) fn get_var_name_and_span_for_region(
|
||||
|
|
|
@ -6,9 +6,10 @@ pub use Ty::*;
|
|||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{self as ast, Expr, GenericArg, GenericParamKind, Generics, SelfKind};
|
||||
use rustc_expand::base::ExtCtxt;
|
||||
use rustc_span::source_map::{respan, DUMMY_SP};
|
||||
use rustc_span::source_map::respan;
|
||||
use rustc_span::symbol::{kw, Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::DUMMY_SP;
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
/// A path, e.g., `::std::option::Option::<i32>` (global). Has support
|
||||
|
|
|
@ -68,7 +68,6 @@ rm -r tests/run-make/split-debuginfo # same
|
|||
rm -r tests/run-make/symbols-include-type-name # --emit=asm not supported
|
||||
rm -r tests/run-make/target-specs # i686 not supported by Cranelift
|
||||
rm -r tests/run-make/mismatching-target-triples # same
|
||||
rm -r tests/run-make/use-extern-for-plugins # same
|
||||
rm tests/ui/asm/x86_64/issue-82869.rs # vector regs in inline asm not yet supported
|
||||
rm tests/ui/asm/x86_64/issue-96797.rs # const and sym inline asm operands don't work entirely correctly
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ path = "tests/lang_tests_release.rs"
|
|||
harness = false
|
||||
|
||||
[features]
|
||||
default = ["master"]
|
||||
master = ["gccjit/master"]
|
||||
|
||||
[dependencies]
|
||||
|
|
|
@ -25,7 +25,7 @@ else
|
|||
exit 1
|
||||
fi
|
||||
|
||||
HOST_TRIPLE=$(rustc -vV | grep host | cut -d: -f2 | tr -d " ")
|
||||
HOST_TRIPLE=$($RUSTC -vV | grep host | cut -d: -f2 | tr -d " ")
|
||||
# TODO: remove $OVERWRITE_TARGET_TRIPLE when config.sh is removed.
|
||||
TARGET_TRIPLE="${OVERWRITE_TARGET_TRIPLE:-$HOST_TRIPLE}"
|
||||
|
||||
|
@ -54,6 +54,10 @@ if [[ -z "$BUILTIN_BACKEND" ]]; then
|
|||
export RUSTFLAGS="$CG_RUSTFLAGS $linker -Csymbol-mangling-version=v0 -Cdebuginfo=2 $disable_lto_flags -Zcodegen-backend=$(pwd)/target/${CHANNEL:-debug}/librustc_codegen_gcc.$dylib_ext --sysroot $(pwd)/build_sysroot/sysroot $TEST_FLAGS"
|
||||
else
|
||||
export RUSTFLAGS="$CG_RUSTFLAGS $linker -Csymbol-mangling-version=v0 -Cdebuginfo=2 $disable_lto_flags -Zcodegen-backend=gcc $TEST_FLAGS -Cpanic=abort"
|
||||
|
||||
if [[ ! -z "$RUSTC_SYSROOT" ]]; then
|
||||
export RUSTFLAGS="$RUSTFLAGS --sysroot $RUSTC_SYSROOT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# FIXME(antoyo): remove once the atomic shim is gone
|
||||
|
|
|
@ -18,7 +18,7 @@ extern "C" {
|
|||
}
|
||||
|
||||
#[panic_handler]
|
||||
fn panic_handler(_: &core::panic::PanicInfo) -> ! {
|
||||
fn panic_handler(_: &core::panic::PanicInfo<'_>) -> ! {
|
||||
core::intrinsics::abort();
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#![no_std]
|
||||
#![feature(allocator_api, rustc_private)]
|
||||
#![cfg_attr(any(unix, target_os = "redox"), feature(libc))]
|
||||
|
||||
// The minimum alignment guaranteed by the architecture. This value is used to
|
||||
// add fast paths for low alignment values.
|
||||
|
@ -48,7 +47,18 @@ mod realloc_fallback {
|
|||
}
|
||||
#[cfg(any(unix, target_os = "redox"))]
|
||||
mod platform {
|
||||
extern crate libc;
|
||||
mod libc {
|
||||
use core::ffi::{c_void, c_int};
|
||||
|
||||
#[link(name = "c")]
|
||||
extern "C" {
|
||||
pub fn malloc(size: usize) -> *mut c_void;
|
||||
pub fn realloc(ptr: *mut c_void, size: usize) -> *mut c_void;
|
||||
pub fn calloc(nmemb: usize, size: usize) -> *mut c_void;
|
||||
pub fn free(ptr: *mut u8);
|
||||
pub fn posix_memalign(memptr: *mut *mut c_void, alignment: usize, size: usize) -> c_int;
|
||||
}
|
||||
}
|
||||
use core::ptr;
|
||||
use MIN_ALIGN;
|
||||
use System;
|
||||
|
@ -82,12 +92,12 @@ mod platform {
|
|||
}
|
||||
#[inline]
|
||||
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
|
||||
libc::free(ptr as *mut libc::c_void)
|
||||
libc::free(ptr as *mut _)
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
|
||||
if layout.align() <= MIN_ALIGN && layout.align() <= new_size {
|
||||
libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8
|
||||
libc::realloc(ptr as *mut _, new_size) as *mut u8
|
||||
} else {
|
||||
self.realloc_fallback(ptr, layout, new_size)
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
extern {}
|
||||
|
||||
#[panic_handler]
|
||||
fn panic_handler(_: &core::panic::PanicInfo) -> ! {
|
||||
fn panic_handler(_: &core::panic::PanicInfo<'_>) -> ! {
|
||||
core::intrinsics::abort();
|
||||
}
|
||||
|
||||
|
|
|
@ -26,8 +26,8 @@ use rustc_middle::{bug, span_bug};
|
|||
use rustc_session::config::{BranchProtection, CFGuard, CFProtection};
|
||||
use rustc_session::config::{CrateType, DebugInfo, PAuthKey, PacRet};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::Span;
|
||||
use rustc_target::abi::{
|
||||
call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx,
|
||||
};
|
||||
|
|
|
@ -17,8 +17,7 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
|
|||
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
|
||||
use rustc_middle::ty::{self, Instance, Ty};
|
||||
use rustc_session::config::OptLevel;
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::{sym, Symbol};
|
||||
use rustc_span::{sym, Span, Symbol};
|
||||
use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode, Reg};
|
||||
use rustc_target::abi::{self, HasDataLayout, WrappingRange};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
|
|
@ -13,7 +13,7 @@ use rustc_middle::ty::cast::{CastTy, IntTy};
|
|||
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
|
||||
use rustc_middle::ty::{self, adjustment::PointerCoercion, Instance, Ty, TyCtxt};
|
||||
use rustc_session::config::OptLevel;
|
||||
use rustc_span::source_map::{Span, DUMMY_SP};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_target::abi::{self, FIRST_VARIANT};
|
||||
|
||||
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
|
|
|
@ -10,7 +10,7 @@ use rustc_middle::traits::Reveal;
|
|||
use rustc_middle::ty::layout::LayoutOf;
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::Span;
|
||||
use rustc_target::abi::{self, Abi};
|
||||
|
||||
use super::{CanAccessStatics, CompileTimeEvalContext, CompileTimeInterpreter};
|
||||
|
@ -106,10 +106,16 @@ pub(crate) fn mk_eval_cx<'mir, 'tcx>(
|
|||
}
|
||||
|
||||
/// This function converts an interpreter value into a MIR constant.
|
||||
///
|
||||
/// The `for_diagnostics` flag turns the usual rules for returning `ConstValue::Scalar` into a
|
||||
/// best-effort attempt. This is not okay for use in const-eval sine it breaks invariants rustc
|
||||
/// relies on, but it is okay for diagnostics which will just give up gracefully when they
|
||||
/// encounter an `Indirect` they cannot handle.
|
||||
#[instrument(skip(ecx), level = "debug")]
|
||||
pub(super) fn op_to_const<'tcx>(
|
||||
ecx: &CompileTimeEvalContext<'_, 'tcx>,
|
||||
op: &OpTy<'tcx>,
|
||||
for_diagnostics: bool,
|
||||
) -> ConstValue<'tcx> {
|
||||
// Handle ZST consistently and early.
|
||||
if op.layout.is_zst() {
|
||||
|
@ -133,7 +139,13 @@ pub(super) fn op_to_const<'tcx>(
|
|||
_ => false,
|
||||
};
|
||||
let immediate = if force_as_immediate {
|
||||
Right(ecx.read_immediate(op).expect("normalization works on validated constants"))
|
||||
match ecx.read_immediate(op) {
|
||||
Ok(imm) => Right(imm),
|
||||
Err(err) if !for_diagnostics => {
|
||||
panic!("normalization works on validated constants: {err:?}")
|
||||
}
|
||||
_ => op.as_mplace_or_imm(),
|
||||
}
|
||||
} else {
|
||||
op.as_mplace_or_imm()
|
||||
};
|
||||
|
@ -205,7 +217,7 @@ pub(crate) fn turn_into_const_value<'tcx>(
|
|||
);
|
||||
|
||||
// Turn this into a proper constant.
|
||||
op_to_const(&ecx, &mplace.into())
|
||||
op_to_const(&ecx, &mplace.into(), /* for diagnostics */ false)
|
||||
}
|
||||
|
||||
#[instrument(skip(tcx), level = "debug")]
|
||||
|
|
|
@ -6,7 +6,7 @@ use rustc_middle::mir;
|
|||
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
|
||||
use rustc_middle::query::TyCtxtAt;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::source_map::DUMMY_SP;
|
||||
use rustc_span::DUMMY_SP;
|
||||
|
||||
mod error;
|
||||
mod eval_queries;
|
||||
|
@ -72,7 +72,7 @@ pub(crate) fn eval_to_valtree<'tcx>(
|
|||
}
|
||||
|
||||
#[instrument(skip(tcx), level = "debug")]
|
||||
pub(crate) fn try_destructure_mir_constant_for_diagnostics<'tcx>(
|
||||
pub(crate) fn try_destructure_mir_constant_for_user_output<'tcx>(
|
||||
tcx: TyCtxtAt<'tcx>,
|
||||
val: mir::ConstValue<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
|
@ -99,7 +99,7 @@ pub(crate) fn try_destructure_mir_constant_for_diagnostics<'tcx>(
|
|||
let fields_iter = (0..field_count)
|
||||
.map(|i| {
|
||||
let field_op = ecx.project_field(&down, i).ok()?;
|
||||
let val = op_to_const(&ecx, &field_op);
|
||||
let val = op_to_const(&ecx, &field_op, /* for diagnostics */ true);
|
||||
Some((val, field_op.layout.ty))
|
||||
})
|
||||
.collect::<Option<Vec<_>>>()?;
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::interpret::{
|
|||
use rustc_middle::mir;
|
||||
use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
|
||||
use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
|
||||
use rustc_span::source_map::DUMMY_SP;
|
||||
use rustc_span::DUMMY_SP;
|
||||
use rustc_target::abi::VariantIdx;
|
||||
|
||||
#[instrument(skip(ecx), level = "debug")]
|
||||
|
@ -232,7 +232,7 @@ pub fn valtree_to_const_value<'tcx>(
|
|||
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, CanAccessStatics::No);
|
||||
let imm = valtree_to_ref(&mut ecx, valtree, *inner_ty);
|
||||
let imm = ImmTy::from_immediate(imm, tcx.layout_of(param_env_ty).unwrap());
|
||||
op_to_const(&ecx, &imm.into())
|
||||
op_to_const(&ecx, &imm.into(), /* for diagnostics */ false)
|
||||
}
|
||||
ty::Tuple(_) | ty::Array(_, _) | ty::Adt(..) => {
|
||||
let layout = tcx.layout_of(param_env_ty).unwrap();
|
||||
|
@ -265,7 +265,7 @@ pub fn valtree_to_const_value<'tcx>(
|
|||
dump_place(&ecx, &place);
|
||||
intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &place).unwrap();
|
||||
|
||||
op_to_const(&ecx, &place.into())
|
||||
op_to_const(&ecx, &place.into(), /* for diagnostics */ false)
|
||||
}
|
||||
ty::Never
|
||||
| ty::Error(_)
|
||||
|
|
|
@ -145,16 +145,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
assert!(dest.layout.is_sized());
|
||||
assert_eq!(cast_ty, dest.layout.ty); // we otherwise ignore `cast_ty` enirely...
|
||||
if src.layout.size != dest.layout.size {
|
||||
let src_bytes = src.layout.size.bytes();
|
||||
let dest_bytes = dest.layout.size.bytes();
|
||||
let src_ty = format!("{}", src.layout.ty);
|
||||
let dest_ty = format!("{}", dest.layout.ty);
|
||||
throw_ub_custom!(
|
||||
fluent::const_eval_invalid_transmute,
|
||||
src_bytes = src_bytes,
|
||||
dest_bytes = dest_bytes,
|
||||
src = src_ty,
|
||||
dest = dest_ty,
|
||||
src_bytes = src.layout.size.bytes(),
|
||||
dest_bytes = dest.layout.size.bytes(),
|
||||
src = src.layout.ty,
|
||||
dest = dest.layout.ty,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -54,8 +54,8 @@ pub fn provide(providers: &mut Providers) {
|
|||
let (param_env, raw) = param_env_and_value.into_parts();
|
||||
const_eval::eval_to_valtree(tcx, param_env, raw)
|
||||
};
|
||||
providers.hooks.try_destructure_mir_constant_for_diagnostics =
|
||||
const_eval::try_destructure_mir_constant_for_diagnostics;
|
||||
providers.hooks.try_destructure_mir_constant_for_user_output =
|
||||
const_eval::try_destructure_mir_constant_for_user_output;
|
||||
providers.valtree_to_const_val = |tcx, (ty, valtree)| {
|
||||
const_eval::valtree_to_const_value(tcx, ty::ParamEnv::empty().and(ty), valtree)
|
||||
};
|
||||
|
|
|
@ -39,7 +39,6 @@ rustc_mir_transform = { path = "../rustc_mir_transform" }
|
|||
rustc_monomorphize = { path = "../rustc_monomorphize" }
|
||||
rustc_parse = { path = "../rustc_parse" }
|
||||
rustc_passes = { path = "../rustc_passes" }
|
||||
rustc_plugin_impl = { path = "../rustc_plugin_impl" }
|
||||
rustc_privacy = { path = "../rustc_privacy" }
|
||||
rustc_query_system = { path = "../rustc_query_system" }
|
||||
rustc_resolve = { path = "../rustc_resolve" }
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
#[macro_use]
|
||||
extern crate tracing;
|
||||
|
||||
pub extern crate rustc_plugin_impl as plugin;
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_codegen_ssa::{traits::CodegenBackend, CodegenErrors, CodegenResults};
|
||||
use rustc_data_structures::profiling::{
|
||||
|
@ -43,8 +41,9 @@ use rustc_session::cstore::MetadataLoader;
|
|||
use rustc_session::getopts::{self, Matches};
|
||||
use rustc_session::lint::{Lint, LintId};
|
||||
use rustc_session::{config, EarlyErrorHandler, Session};
|
||||
use rustc_span::source_map::{FileLoader, FileName};
|
||||
use rustc_span::source_map::FileLoader;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::FileName;
|
||||
use rustc_target::json::ToJson;
|
||||
use rustc_target::spec::{Target, TargetTriple};
|
||||
|
||||
|
@ -131,7 +130,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[
|
|||
rustc_monomorphize::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_parse::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_passes::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_plugin_impl::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_privacy::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_query_system::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_resolve::DEFAULT_LOCALE_RESOURCE,
|
||||
|
@ -993,16 +991,14 @@ the command line flag directly.
|
|||
}
|
||||
|
||||
/// Write to stdout lint command options, together with a list of all available lints
|
||||
pub fn describe_lints(sess: &Session, lint_store: &LintStore, loaded_plugins: bool) {
|
||||
pub fn describe_lints(sess: &Session, lint_store: &LintStore, loaded_lints: bool) {
|
||||
safe_println!(
|
||||
"
|
||||
Available lint options:
|
||||
-W <foo> Warn about <foo>
|
||||
-A <foo> \
|
||||
Allow <foo>
|
||||
-A <foo> Allow <foo>
|
||||
-D <foo> Deny <foo>
|
||||
-F <foo> Forbid <foo> \
|
||||
(deny <foo> and all attempts to override)
|
||||
-F <foo> Forbid <foo> (deny <foo> and all attempts to override)
|
||||
|
||||
"
|
||||
);
|
||||
|
@ -1021,18 +1017,18 @@ Available lint options:
|
|||
lints
|
||||
}
|
||||
|
||||
let (plugin, builtin): (Vec<_>, _) =
|
||||
lint_store.get_lints().iter().cloned().partition(|&lint| lint.is_plugin);
|
||||
let plugin = sort_lints(sess, plugin);
|
||||
let (loaded, builtin): (Vec<_>, _) =
|
||||
lint_store.get_lints().iter().cloned().partition(|&lint| lint.is_loaded);
|
||||
let loaded = sort_lints(sess, loaded);
|
||||
let builtin = sort_lints(sess, builtin);
|
||||
|
||||
let (plugin_groups, builtin_groups): (Vec<_>, _) =
|
||||
let (loaded_groups, builtin_groups): (Vec<_>, _) =
|
||||
lint_store.get_lint_groups().partition(|&(.., p)| p);
|
||||
let plugin_groups = sort_lint_groups(plugin_groups);
|
||||
let loaded_groups = sort_lint_groups(loaded_groups);
|
||||
let builtin_groups = sort_lint_groups(builtin_groups);
|
||||
|
||||
let max_name_len =
|
||||
plugin.iter().chain(&builtin).map(|&s| s.name.chars().count()).max().unwrap_or(0);
|
||||
loaded.iter().chain(&builtin).map(|&s| s.name.chars().count()).max().unwrap_or(0);
|
||||
let padded = |x: &str| {
|
||||
let mut s = " ".repeat(max_name_len - x.chars().count());
|
||||
s.push_str(x);
|
||||
|
@ -1060,7 +1056,7 @@ Available lint options:
|
|||
|
||||
let max_name_len = max(
|
||||
"warnings".len(),
|
||||
plugin_groups
|
||||
loaded_groups
|
||||
.iter()
|
||||
.chain(&builtin_groups)
|
||||
.map(|&(s, _)| s.chars().count())
|
||||
|
@ -1098,20 +1094,22 @@ Available lint options:
|
|||
|
||||
print_lint_groups(builtin_groups, true);
|
||||
|
||||
match (loaded_plugins, plugin.len(), plugin_groups.len()) {
|
||||
match (loaded_lints, loaded.len(), loaded_groups.len()) {
|
||||
(false, 0, _) | (false, _, 0) => {
|
||||
safe_println!("Lint tools like Clippy can provide additional lints and lint groups.");
|
||||
safe_println!("Lint tools like Clippy can load additional lints and lint groups.");
|
||||
}
|
||||
(false, ..) => panic!("didn't load additional lints but got them anyway!"),
|
||||
(true, 0, 0) => {
|
||||
safe_println!("This crate does not load any additional lints or lint groups.")
|
||||
}
|
||||
(false, ..) => panic!("didn't load lint plugins but got them anyway!"),
|
||||
(true, 0, 0) => safe_println!("This crate does not load any lint plugins or lint groups."),
|
||||
(true, l, g) => {
|
||||
if l > 0 {
|
||||
safe_println!("Lint checks provided by plugins loaded by this crate:\n");
|
||||
print_lints(plugin);
|
||||
safe_println!("Lint checks loaded by this crate:\n");
|
||||
print_lints(loaded);
|
||||
}
|
||||
if g > 0 {
|
||||
safe_println!("Lint groups provided by plugins loaded by this crate:\n");
|
||||
print_lint_groups(plugin_groups, false);
|
||||
safe_println!("Lint groups loaded by this crate:\n");
|
||||
print_lint_groups(loaded_groups, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1128,7 +1126,7 @@ pub fn describe_flag_categories(handler: &EarlyErrorHandler, matches: &Matches)
|
|||
rustc_errors::FatalError.raise();
|
||||
}
|
||||
|
||||
// Don't handle -W help here, because we might first load plugins.
|
||||
// Don't handle -W help here, because we might first load additional lints.
|
||||
let debug_flags = matches.opt_strs("Z");
|
||||
if debug_flags.iter().any(|x| *x == "help") {
|
||||
describe_debug_flags();
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#### Note: this error code is no longer emitted by the compiler`
|
||||
|
||||
Plugin `..` only found in rlib format, but must be available in dylib format.
|
||||
|
||||
Erroneous code example:
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
A plugin/crate was declared but cannot be found.
|
||||
A crate was declared but cannot be found.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0463
|
||||
#![feature(plugin)]
|
||||
#![plugin(cookie_monster)] // error: can't find crate for `cookie_monster`
|
||||
extern crate cake_is_a_lie; // error: can't find crate for `cake_is_a_lie`
|
||||
extern crate foo; // error: can't find crate
|
||||
```
|
||||
|
||||
You need to link your code to the relevant crate in order to be able to use it
|
||||
(through Cargo or the `-L` option of rustc example). Plugins are crates as
|
||||
well, and you link to them the same way.
|
||||
(through Cargo or the `-L` option of rustc, for example).
|
||||
|
||||
## Common causes
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
#### Note: this error code is no longer emitted by the compiler.
|
||||
|
||||
The `plugin` attribute was malformed.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0498
|
||||
```ignore (E0498 is no longer emitted)
|
||||
#![feature(plugin)]
|
||||
#![plugin(foo(args))] // error: invalid argument
|
||||
#![plugin(bar="test")] // error: invalid argument
|
||||
|
|
|
@ -4,8 +4,8 @@ use rustc_ast::mut_visit::*;
|
|||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::Delimiter;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_span::source_map::DUMMY_SP;
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::DUMMY_SP;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ use rustc_ast as ast;
|
|||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_parse::{new_parser_from_source_str, parser::Parser, source_file_to_stream};
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::create_default_session_if_not_set_then;
|
||||
use rustc_span::create_default_session_globals_then;
|
||||
use rustc_span::source_map::{FilePathMapping, SourceMap};
|
||||
use rustc_span::{BytePos, Span};
|
||||
|
||||
|
@ -181,7 +181,7 @@ impl<T: Write> Write for Shared<T> {
|
|||
}
|
||||
|
||||
fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: &str) {
|
||||
create_default_session_if_not_set_then(|_| {
|
||||
create_default_session_globals_then(|| {
|
||||
let (handler, source_map, output) = create_test_handler();
|
||||
source_map.new_source_file(Path::new("test.rs").to_owned().into(), file_text.to_owned());
|
||||
|
||||
|
|
|
@ -417,24 +417,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
naked_functions, experimental!(naked)
|
||||
),
|
||||
|
||||
// Plugins:
|
||||
BuiltinAttribute {
|
||||
name: sym::plugin,
|
||||
only_local: false,
|
||||
type_: CrateLevel,
|
||||
template: template!(List: "name"),
|
||||
duplicates: DuplicatesOk,
|
||||
gate: Gated(
|
||||
Stability::Deprecated(
|
||||
"https://github.com/rust-lang/rust/pull/64675",
|
||||
Some("may be removed in a future compiler version"),
|
||||
),
|
||||
sym::plugin,
|
||||
"compiler plugins are deprecated",
|
||||
cfg_fn!(plugin)
|
||||
),
|
||||
},
|
||||
|
||||
// Testing:
|
||||
gated!(
|
||||
test_runner, CrateLevel, template!(List: "path"), ErrorFollowing, custom_test_frameworks,
|
||||
|
|
|
@ -152,9 +152,12 @@ declare_features! (
|
|||
Some("removed in favor of `#![feature(marker_trait_attr)]`")),
|
||||
(removed, panic_implementation, "1.28.0", Some(44489), None,
|
||||
Some("subsumed by `#[panic_handler]`")),
|
||||
/// Allows using `#![plugin(myplugin)]`.
|
||||
(removed, plugin, "CURRENT_RUSTC_VERSION", Some(29597), None,
|
||||
Some("plugins are no longer supported")),
|
||||
/// Allows using `#[plugin_registrar]` on functions.
|
||||
(removed, plugin_registrar, "1.54.0", Some(29597), None,
|
||||
Some("a __rustc_plugin_registrar symbol must now be defined instead")),
|
||||
Some("plugins are no longer supported")),
|
||||
(removed, proc_macro_expr, "1.27.0", Some(54727), None,
|
||||
Some("subsumed by `#![feature(proc_macro_hygiene)]`")),
|
||||
(removed, proc_macro_gen, "1.27.0", Some(54727), None,
|
||||
|
|
|
@ -528,8 +528,6 @@ declare_features! (
|
|||
(unstable, object_safe_for_dispatch, "1.40.0", Some(43561), None),
|
||||
/// Allows using `#[optimize(X)]`.
|
||||
(unstable, optimize_attribute, "1.34.0", Some(54882), None),
|
||||
/// Allows using `#![plugin(myplugin)]`.
|
||||
(unstable, plugin, "1.0.0", Some(29597), None),
|
||||
/// Allows exhaustive integer pattern matching on `usize` and `isize`.
|
||||
(unstable, precise_pointer_size_matching, "1.32.0", Some(56354), None),
|
||||
/// Allows macro attributes on expressions, statements and non-inline modules.
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::definitions::{DefKey, DefPathData, DisambiguatedDefPathData};
|
|||
use rustc_data_structures::stable_hasher::Hash64;
|
||||
use rustc_span::def_id::{DefPathHash, StableCrateId};
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::{create_session_if_not_set_then, Symbol};
|
||||
use rustc_span::{create_session_globals_then, Symbol};
|
||||
|
||||
#[test]
|
||||
fn def_path_hash_depends_on_crate_id() {
|
||||
|
@ -14,7 +14,7 @@ fn def_path_hash_depends_on_crate_id() {
|
|||
// the crate by changing the crate disambiguator (e.g. via bumping the
|
||||
// crate's version number).
|
||||
|
||||
create_session_if_not_set_then(Edition::Edition2024, |_| {
|
||||
create_session_globals_then(Edition::Edition2024, || {
|
||||
let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()], "");
|
||||
let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()], "");
|
||||
|
||||
|
|
|
@ -2162,128 +2162,10 @@ pub(super) fn check_type_bounds<'tcx>(
|
|||
impl_ty: ty::AssocItem,
|
||||
impl_trait_ref: ty::TraitRef<'tcx>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let param_env = tcx.param_env(impl_ty.def_id);
|
||||
let container_id = impl_ty.container_id(tcx);
|
||||
// Given
|
||||
//
|
||||
// impl<A, B> Foo<u32> for (A, B) {
|
||||
// type Bar<C> = Wrapper<A, B, C>
|
||||
// }
|
||||
//
|
||||
// - `impl_trait_ref` would be `<(A, B) as Foo<u32>>`
|
||||
// - `normalize_impl_ty_args` would be `[A, B, ^0.0]` (`^0.0` here is the bound var with db 0 and index 0)
|
||||
// - `normalize_impl_ty` would be `Wrapper<A, B, ^0.0>`
|
||||
// - `rebased_args` would be `[(A, B), u32, ^0.0]`, combining the args from
|
||||
// the *trait* with the generic associated type parameters (as bound vars).
|
||||
//
|
||||
// A note regarding the use of bound vars here:
|
||||
// Imagine as an example
|
||||
// ```
|
||||
// trait Family {
|
||||
// type Member<C: Eq>;
|
||||
// }
|
||||
//
|
||||
// impl Family for VecFamily {
|
||||
// type Member<C: Eq> = i32;
|
||||
// }
|
||||
// ```
|
||||
// Here, we would generate
|
||||
// ```notrust
|
||||
// forall<C> { Normalize(<VecFamily as Family>::Member<C> => i32) }
|
||||
// ```
|
||||
// when we really would like to generate
|
||||
// ```notrust
|
||||
// forall<C> { Normalize(<VecFamily as Family>::Member<C> => i32) :- Implemented(C: Eq) }
|
||||
// ```
|
||||
// But, this is probably fine, because although the first clause can be used with types C that
|
||||
// do not implement Eq, for it to cause some kind of problem, there would have to be a
|
||||
// VecFamily::Member<X> for some type X where !(X: Eq), that appears in the value of type
|
||||
// Member<C: Eq> = .... That type would fail a well-formedness check that we ought to be doing
|
||||
// elsewhere, which would check that any <T as Family>::Member<X> meets the bounds declared in
|
||||
// the trait (notably, that X: Eq and T: Family).
|
||||
let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
|
||||
smallvec::SmallVec::with_capacity(tcx.generics_of(impl_ty.def_id).params.len());
|
||||
// Extend the impl's identity args with late-bound GAT vars
|
||||
let normalize_impl_ty_args = ty::GenericArgs::identity_for_item(tcx, container_id).extend_to(
|
||||
tcx,
|
||||
impl_ty.def_id,
|
||||
|param, _| match param.kind {
|
||||
GenericParamDefKind::Type { .. } => {
|
||||
let kind = ty::BoundTyKind::Param(param.def_id, param.name);
|
||||
let bound_var = ty::BoundVariableKind::Ty(kind);
|
||||
bound_vars.push(bound_var);
|
||||
Ty::new_bound(
|
||||
tcx,
|
||||
ty::INNERMOST,
|
||||
ty::BoundTy { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
|
||||
)
|
||||
.into()
|
||||
}
|
||||
GenericParamDefKind::Lifetime => {
|
||||
let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
|
||||
let bound_var = ty::BoundVariableKind::Region(kind);
|
||||
bound_vars.push(bound_var);
|
||||
ty::Region::new_late_bound(
|
||||
tcx,
|
||||
ty::INNERMOST,
|
||||
ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
|
||||
)
|
||||
.into()
|
||||
}
|
||||
GenericParamDefKind::Const { .. } => {
|
||||
let bound_var = ty::BoundVariableKind::Const;
|
||||
bound_vars.push(bound_var);
|
||||
ty::Const::new_bound(
|
||||
tcx,
|
||||
ty::INNERMOST,
|
||||
ty::BoundVar::from_usize(bound_vars.len() - 1),
|
||||
tcx.type_of(param.def_id)
|
||||
.no_bound_vars()
|
||||
.expect("const parameter types cannot be generic"),
|
||||
)
|
||||
.into()
|
||||
}
|
||||
},
|
||||
);
|
||||
// When checking something like
|
||||
//
|
||||
// trait X { type Y: PartialEq<<Self as X>::Y> }
|
||||
// impl X for T { default type Y = S; }
|
||||
//
|
||||
// We will have to prove the bound S: PartialEq<<T as X>::Y>. In this case
|
||||
// we want <T as X>::Y to normalize to S. This is valid because we are
|
||||
// checking the default value specifically here. Add this equality to the
|
||||
// ParamEnv for normalization specifically.
|
||||
let normalize_impl_ty = tcx.type_of(impl_ty.def_id).instantiate(tcx, normalize_impl_ty_args);
|
||||
let rebased_args = normalize_impl_ty_args.rebase_onto(tcx, container_id, impl_trait_ref.args);
|
||||
let bound_vars = tcx.mk_bound_variable_kinds(&bound_vars);
|
||||
let normalize_param_env = {
|
||||
let mut predicates = param_env.caller_bounds().iter().collect::<Vec<_>>();
|
||||
match normalize_impl_ty.kind() {
|
||||
ty::Alias(ty::Projection, proj)
|
||||
if proj.def_id == trait_ty.def_id && proj.args == rebased_args =>
|
||||
{
|
||||
// Don't include this predicate if the projected type is
|
||||
// exactly the same as the projection. This can occur in
|
||||
// (somewhat dubious) code like this:
|
||||
//
|
||||
// impl<T> X for T where T: X { type Y = <T as X>::Y; }
|
||||
}
|
||||
_ => predicates.push(
|
||||
ty::Binder::bind_with_vars(
|
||||
ty::ProjectionPredicate {
|
||||
projection_ty: ty::AliasTy::new(tcx, trait_ty.def_id, rebased_args),
|
||||
term: normalize_impl_ty.into(),
|
||||
},
|
||||
bound_vars,
|
||||
)
|
||||
.to_predicate(tcx),
|
||||
),
|
||||
};
|
||||
ty::ParamEnv::new(tcx.mk_clauses(&predicates), Reveal::UserFacing)
|
||||
};
|
||||
debug!(?normalize_param_env);
|
||||
let param_env = param_env_with_gat_bounds(tcx, impl_ty, impl_trait_ref);
|
||||
debug!(?param_env);
|
||||
|
||||
let container_id = impl_ty.container_id(tcx);
|
||||
let impl_ty_def_id = impl_ty.def_id.expect_local();
|
||||
let impl_ty_args = GenericArgs::identity_for_item(tcx, impl_ty.def_id);
|
||||
let rebased_args = impl_ty_args.rebase_onto(tcx, container_id, impl_trait_ref.args);
|
||||
|
@ -2336,8 +2218,7 @@ pub(super) fn check_type_bounds<'tcx>(
|
|||
debug!("check_type_bounds: item_bounds={:?}", obligations);
|
||||
|
||||
for mut obligation in util::elaborate(tcx, obligations) {
|
||||
let normalized_predicate =
|
||||
ocx.normalize(&normalize_cause, normalize_param_env, obligation.predicate);
|
||||
let normalized_predicate = ocx.normalize(&normalize_cause, param_env, obligation.predicate);
|
||||
debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
|
||||
obligation.predicate = normalized_predicate;
|
||||
|
||||
|
@ -2358,6 +2239,171 @@ pub(super) fn check_type_bounds<'tcx>(
|
|||
ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env)
|
||||
}
|
||||
|
||||
/// Install projection predicates that allow GATs to project to their own
|
||||
/// definition types. This is not allowed in general in cases of default
|
||||
/// associated types in trait definitions, or when specialization is involved,
|
||||
/// but is needed when checking these definition types actually satisfy the
|
||||
/// trait bounds of the GAT.
|
||||
///
|
||||
/// # How it works
|
||||
///
|
||||
/// ```ignore (example)
|
||||
/// impl<A, B> Foo<u32> for (A, B) {
|
||||
/// type Bar<C> = Wrapper<A, B, C>
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// - `impl_trait_ref` would be `<(A, B) as Foo<u32>>`
|
||||
/// - `normalize_impl_ty_args` would be `[A, B, ^0.0]` (`^0.0` here is the bound var with db 0 and index 0)
|
||||
/// - `normalize_impl_ty` would be `Wrapper<A, B, ^0.0>`
|
||||
/// - `rebased_args` would be `[(A, B), u32, ^0.0]`, combining the args from
|
||||
/// the *trait* with the generic associated type parameters (as bound vars).
|
||||
///
|
||||
/// A note regarding the use of bound vars here:
|
||||
/// Imagine as an example
|
||||
/// ```
|
||||
/// trait Family {
|
||||
/// type Member<C: Eq>;
|
||||
/// }
|
||||
///
|
||||
/// impl Family for VecFamily {
|
||||
/// type Member<C: Eq> = i32;
|
||||
/// }
|
||||
/// ```
|
||||
/// Here, we would generate
|
||||
/// ```ignore (pseudo-rust)
|
||||
/// forall<C> { Normalize(<VecFamily as Family>::Member<C> => i32) }
|
||||
/// ```
|
||||
///
|
||||
/// when we really would like to generate
|
||||
/// ```ignore (pseudo-rust)
|
||||
/// forall<C> { Normalize(<VecFamily as Family>::Member<C> => i32) :- Implemented(C: Eq) }
|
||||
/// ```
|
||||
///
|
||||
/// But, this is probably fine, because although the first clause can be used with types `C` that
|
||||
/// do not implement `Eq`, for it to cause some kind of problem, there would have to be a
|
||||
/// `VecFamily::Member<X>` for some type `X` where `!(X: Eq)`, that appears in the value of type
|
||||
/// `Member<C: Eq> = ....` That type would fail a well-formedness check that we ought to be doing
|
||||
/// elsewhere, which would check that any `<T as Family>::Member<X>` meets the bounds declared in
|
||||
/// the trait (notably, that `X: Eq` and `T: Family`).
|
||||
fn param_env_with_gat_bounds<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
impl_ty: ty::AssocItem,
|
||||
impl_trait_ref: ty::TraitRef<'tcx>,
|
||||
) -> ty::ParamEnv<'tcx> {
|
||||
let param_env = tcx.param_env(impl_ty.def_id);
|
||||
let container_id = impl_ty.container_id(tcx);
|
||||
let mut predicates = param_env.caller_bounds().to_vec();
|
||||
|
||||
// for RPITITs, we should install predicates that allow us to project all
|
||||
// of the RPITITs associated with the same body. This is because checking
|
||||
// the item bounds of RPITITs often involves nested RPITITs having to prove
|
||||
// bounds about themselves.
|
||||
let impl_tys_to_install = match impl_ty.opt_rpitit_info {
|
||||
None => vec![impl_ty],
|
||||
Some(
|
||||
ty::ImplTraitInTraitData::Impl { fn_def_id }
|
||||
| ty::ImplTraitInTraitData::Trait { fn_def_id, .. },
|
||||
) => tcx
|
||||
.associated_types_for_impl_traits_in_associated_fn(fn_def_id)
|
||||
.iter()
|
||||
.map(|def_id| tcx.associated_item(*def_id))
|
||||
.collect(),
|
||||
};
|
||||
|
||||
for impl_ty in impl_tys_to_install {
|
||||
let trait_ty = match impl_ty.container {
|
||||
ty::AssocItemContainer::TraitContainer => impl_ty,
|
||||
ty::AssocItemContainer::ImplContainer => {
|
||||
tcx.associated_item(impl_ty.trait_item_def_id.unwrap())
|
||||
}
|
||||
};
|
||||
|
||||
let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
|
||||
smallvec::SmallVec::with_capacity(tcx.generics_of(impl_ty.def_id).params.len());
|
||||
// Extend the impl's identity args with late-bound GAT vars
|
||||
let normalize_impl_ty_args = ty::GenericArgs::identity_for_item(tcx, container_id)
|
||||
.extend_to(tcx, impl_ty.def_id, |param, _| match param.kind {
|
||||
GenericParamDefKind::Type { .. } => {
|
||||
let kind = ty::BoundTyKind::Param(param.def_id, param.name);
|
||||
let bound_var = ty::BoundVariableKind::Ty(kind);
|
||||
bound_vars.push(bound_var);
|
||||
Ty::new_bound(
|
||||
tcx,
|
||||
ty::INNERMOST,
|
||||
ty::BoundTy { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
|
||||
)
|
||||
.into()
|
||||
}
|
||||
GenericParamDefKind::Lifetime => {
|
||||
let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
|
||||
let bound_var = ty::BoundVariableKind::Region(kind);
|
||||
bound_vars.push(bound_var);
|
||||
ty::Region::new_late_bound(
|
||||
tcx,
|
||||
ty::INNERMOST,
|
||||
ty::BoundRegion {
|
||||
var: ty::BoundVar::from_usize(bound_vars.len() - 1),
|
||||
kind,
|
||||
},
|
||||
)
|
||||
.into()
|
||||
}
|
||||
GenericParamDefKind::Const { .. } => {
|
||||
let bound_var = ty::BoundVariableKind::Const;
|
||||
bound_vars.push(bound_var);
|
||||
ty::Const::new_bound(
|
||||
tcx,
|
||||
ty::INNERMOST,
|
||||
ty::BoundVar::from_usize(bound_vars.len() - 1),
|
||||
tcx.type_of(param.def_id)
|
||||
.no_bound_vars()
|
||||
.expect("const parameter types cannot be generic"),
|
||||
)
|
||||
.into()
|
||||
}
|
||||
});
|
||||
// When checking something like
|
||||
//
|
||||
// trait X { type Y: PartialEq<<Self as X>::Y> }
|
||||
// impl X for T { default type Y = S; }
|
||||
//
|
||||
// We will have to prove the bound S: PartialEq<<T as X>::Y>. In this case
|
||||
// we want <T as X>::Y to normalize to S. This is valid because we are
|
||||
// checking the default value specifically here. Add this equality to the
|
||||
// ParamEnv for normalization specifically.
|
||||
let normalize_impl_ty =
|
||||
tcx.type_of(impl_ty.def_id).instantiate(tcx, normalize_impl_ty_args);
|
||||
let rebased_args =
|
||||
normalize_impl_ty_args.rebase_onto(tcx, container_id, impl_trait_ref.args);
|
||||
let bound_vars = tcx.mk_bound_variable_kinds(&bound_vars);
|
||||
|
||||
match normalize_impl_ty.kind() {
|
||||
ty::Alias(ty::Projection, proj)
|
||||
if proj.def_id == trait_ty.def_id && proj.args == rebased_args =>
|
||||
{
|
||||
// Don't include this predicate if the projected type is
|
||||
// exactly the same as the projection. This can occur in
|
||||
// (somewhat dubious) code like this:
|
||||
//
|
||||
// impl<T> X for T where T: X { type Y = <T as X>::Y; }
|
||||
}
|
||||
_ => predicates.push(
|
||||
ty::Binder::bind_with_vars(
|
||||
ty::ProjectionPredicate {
|
||||
projection_ty: ty::AliasTy::new(tcx, trait_ty.def_id, rebased_args),
|
||||
term: normalize_impl_ty.into(),
|
||||
},
|
||||
bound_vars,
|
||||
)
|
||||
.to_predicate(tcx),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
ty::ParamEnv::new(tcx.mk_clauses(&predicates), Reveal::UserFacing)
|
||||
}
|
||||
|
||||
fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str {
|
||||
match impl_item.kind {
|
||||
ty::AssocKind::Const => "const",
|
||||
|
|
|
@ -90,9 +90,8 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
|||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{GenericArgs, GenericArgsRef};
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::source_map::DUMMY_SP;
|
||||
use rustc_span::symbol::{kw, Ident};
|
||||
use rustc_span::{self, def_id::CRATE_DEF_ID, BytePos, Span, Symbol};
|
||||
use rustc_span::{self, def_id::CRATE_DEF_ID, BytePos, Span, Symbol, DUMMY_SP};
|
||||
use rustc_target::abi::VariantIdx;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor;
|
||||
|
|
|
@ -880,7 +880,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
|||
(pair, r)
|
||||
})
|
||||
.unzip();
|
||||
self.record_late_bound_vars(hir_id, binders.clone());
|
||||
self.record_late_bound_vars(hir_id, binders);
|
||||
// Even if there are no lifetimes defined here, we still wrap it in a binder
|
||||
// scope. If there happens to be a nested poly trait ref (an error), that
|
||||
// will be `Concatenating` anyways, so we don't have to worry about the depth
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::Span;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||
|
|
|
@ -14,8 +14,7 @@ use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
|
|||
use rustc_middle::ty::GenericArgs;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::sym;
|
||||
use rustc_span::{sym, Span};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use rustc_trait_selection::traits;
|
||||
use rustc_trait_selection::traits::error_reporting::ArgKind;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use rustc_span::source_map::DUMMY_SP;
|
||||
use rustc_span::{self, Span};
|
||||
use rustc_span::{self, Span, DUMMY_SP};
|
||||
use std::{cmp, ops};
|
||||
|
||||
/// Tracks whether executing a node may exit normally (versus
|
||||
|
|
|
@ -52,8 +52,9 @@ use rustc_session::errors::ExprParenthesesNeeded;
|
|||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::edit_distance::find_best_match_for_name;
|
||||
use rustc_span::hygiene::DesugaringKind;
|
||||
use rustc_span::source_map::{Span, Spanned};
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
|
||||
use rustc_target::spec::abi::Abi::RustIntrinsic;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
|
|
|
@ -17,8 +17,9 @@ use rustc_middle::ty::{self, Adt, BindingMode, Ty, TypeVisitableExt};
|
|||
use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
|
||||
use rustc_span::edit_distance::find_best_match_for_name;
|
||||
use rustc_span::hygiene::DesugaringKind;
|
||||
use rustc_span::source_map::{Span, Spanned};
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::{BytePos, DUMMY_SP};
|
||||
use rustc_target::abi::FieldIdx;
|
||||
use rustc_trait_selection::traits::{ObligationCause, Pattern};
|
||||
|
|
|
@ -27,7 +27,7 @@ use rustc_index::IndexVec;
|
|||
use rustc_middle::ty::fold::TypeFoldable;
|
||||
use rustc_middle::ty::GenericArg;
|
||||
use rustc_middle::ty::{self, List, Ty, TyCtxt};
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::Span;
|
||||
|
||||
pub use rustc_middle::infer::canonical::*;
|
||||
pub use substitute::CanonicalExt;
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::infer::lexical_region_resolve::RegionResolutionError;
|
|||
use crate::infer::lexical_region_resolve::RegionResolutionError::*;
|
||||
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::Span;
|
||||
|
||||
mod different_lifetimes;
|
||||
pub mod find_anon_type;
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
|
||||
use rustc_middle::ty::{
|
||||
self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
|
||||
};
|
||||
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
|
@ -49,6 +51,12 @@ where
|
|||
return ControlFlow::Continue(());
|
||||
}
|
||||
|
||||
// FIXME: Don't consider alias bounds on types that have escaping bound
|
||||
// vars. See #117455.
|
||||
if ty.has_escaping_bound_vars() {
|
||||
return ty.super_visit_with(self);
|
||||
}
|
||||
|
||||
match ty.kind() {
|
||||
// We can prove that an alias is live two ways:
|
||||
// 1. All the components are live.
|
||||
|
|
|
@ -36,7 +36,6 @@ rustc_mir_transform = { path = "../rustc_mir_transform" }
|
|||
rustc_monomorphize = { path = "../rustc_monomorphize" }
|
||||
rustc_parse = { path = "../rustc_parse" }
|
||||
rustc_passes = { path = "../rustc_passes" }
|
||||
rustc_plugin_impl = { path = "../rustc_plugin_impl" }
|
||||
rustc_privacy = { path = "../rustc_privacy" }
|
||||
rustc_query_impl = { path = "../rustc_query_impl" }
|
||||
rustc_query_system = { path = "../rustc_query_system" }
|
||||
|
|
|
@ -21,8 +21,9 @@ use rustc_session::config::{
|
|||
use rustc_session::filesearch::sysroot_candidates;
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_session::{lint, CompilerIO, EarlyErrorHandler, Session};
|
||||
use rustc_span::source_map::{FileLoader, FileName};
|
||||
use rustc_span::source_map::FileLoader;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::FileName;
|
||||
use std::path::PathBuf;
|
||||
use std::result;
|
||||
use std::sync::Arc;
|
||||
|
@ -353,7 +354,7 @@ pub struct Config {
|
|||
pub hash_untracked_state: Option<Box<dyn FnOnce(&Session, &mut StableHasher) + Send>>,
|
||||
|
||||
/// This is a callback from the driver that is called when we're registering lints;
|
||||
/// it is called during plugin registration when we have the LintStore in a non-shared state.
|
||||
/// it is called during lint loading when we have the LintStore in a non-shared state.
|
||||
///
|
||||
/// Note that if you find a Some here you probably want to call that function in the new
|
||||
/// function being registered.
|
||||
|
|
|
@ -23,11 +23,10 @@ use rustc_middle::util::Providers;
|
|||
use rustc_mir_build as mir_build;
|
||||
use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_attr};
|
||||
use rustc_passes::{self, abi_test, hir_stats, layout_test};
|
||||
use rustc_plugin_impl as plugin;
|
||||
use rustc_resolve::Resolver;
|
||||
use rustc_session::code_stats::VTableSizeInfo;
|
||||
use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType};
|
||||
use rustc_session::cstore::{MetadataLoader, Untracked};
|
||||
use rustc_session::cstore::Untracked;
|
||||
use rustc_session::output::filename_for_input;
|
||||
use rustc_session::search_paths::PathKind;
|
||||
use rustc_session::{Limit, Session};
|
||||
|
@ -75,25 +74,12 @@ fn count_nodes(krate: &ast::Crate) -> usize {
|
|||
|
||||
pub(crate) fn create_lint_store(
|
||||
sess: &Session,
|
||||
metadata_loader: &dyn MetadataLoader,
|
||||
register_lints: Option<impl Fn(&Session, &mut LintStore)>,
|
||||
pre_configured_attrs: &[ast::Attribute],
|
||||
) -> LintStore {
|
||||
let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints());
|
||||
if let Some(register_lints) = register_lints {
|
||||
register_lints(sess, &mut lint_store);
|
||||
}
|
||||
|
||||
let registrars = sess.time("plugin_loading", || {
|
||||
plugin::load::load_plugins(sess, metadata_loader, pre_configured_attrs)
|
||||
});
|
||||
sess.time("plugin_registration", || {
|
||||
let mut registry = plugin::Registry { lint_store: &mut lint_store };
|
||||
for registrar in registrars {
|
||||
registrar(&mut registry);
|
||||
}
|
||||
});
|
||||
|
||||
lint_store
|
||||
}
|
||||
|
||||
|
|
|
@ -148,12 +148,8 @@ impl<'tcx> Queries<'tcx> {
|
|||
);
|
||||
let dep_graph = setup_dep_graph(sess, crate_name, stable_crate_id)?;
|
||||
|
||||
let lint_store = Lrc::new(passes::create_lint_store(
|
||||
sess,
|
||||
&*self.codegen_backend().metadata_loader(),
|
||||
self.compiler.register_lints.as_deref(),
|
||||
&pre_configured_attrs,
|
||||
));
|
||||
let lint_store =
|
||||
Lrc::new(passes::create_lint_store(sess, self.compiler.register_lints.as_deref()));
|
||||
let cstore = FreezeLock::new(Box::new(CStore::new(
|
||||
self.codegen_backend().metadata_loader(),
|
||||
stable_crate_id,
|
||||
|
|
|
@ -817,7 +817,6 @@ fn test_unstable_options_tracking_hash() {
|
|||
tracked!(split_lto_unit, Some(true));
|
||||
tracked!(src_hash_algorithm, Some(SourceFileHashAlgorithm::Sha1));
|
||||
tracked!(stack_protector, StackProtector::All);
|
||||
tracked!(symbol_mangling_version, Some(SymbolManglingVersion::V0));
|
||||
tracked!(teach, true);
|
||||
tracked!(thinlto, Some(true));
|
||||
tracked!(thir_unsafeck, true);
|
||||
|
|
|
@ -109,7 +109,7 @@ struct LintAlias {
|
|||
|
||||
struct LintGroup {
|
||||
lint_ids: Vec<LintId>,
|
||||
from_plugin: bool,
|
||||
is_loaded: bool,
|
||||
depr: Option<LintAlias>,
|
||||
}
|
||||
|
||||
|
@ -160,9 +160,7 @@ impl LintStore {
|
|||
// Don't display deprecated lint groups.
|
||||
depr.is_none()
|
||||
})
|
||||
.map(|(k, LintGroup { lint_ids, from_plugin, .. })| {
|
||||
(*k, lint_ids.clone(), *from_plugin)
|
||||
})
|
||||
.map(|(k, LintGroup { lint_ids, is_loaded, .. })| (*k, lint_ids.clone(), *is_loaded))
|
||||
}
|
||||
|
||||
pub fn register_early_pass(
|
||||
|
@ -221,7 +219,7 @@ impl LintStore {
|
|||
.entry(edition.lint_name())
|
||||
.or_insert(LintGroup {
|
||||
lint_ids: vec![],
|
||||
from_plugin: lint.is_plugin,
|
||||
is_loaded: lint.is_loaded,
|
||||
depr: None,
|
||||
})
|
||||
.lint_ids
|
||||
|
@ -234,7 +232,7 @@ impl LintStore {
|
|||
.entry("future_incompatible")
|
||||
.or_insert(LintGroup {
|
||||
lint_ids: vec![],
|
||||
from_plugin: lint.is_plugin,
|
||||
is_loaded: lint.is_loaded,
|
||||
depr: None,
|
||||
})
|
||||
.lint_ids
|
||||
|
@ -249,7 +247,7 @@ impl LintStore {
|
|||
alias,
|
||||
LintGroup {
|
||||
lint_ids: vec![],
|
||||
from_plugin: false,
|
||||
is_loaded: false,
|
||||
depr: Some(LintAlias { name: lint_name, silent: true }),
|
||||
},
|
||||
);
|
||||
|
@ -257,21 +255,21 @@ impl LintStore {
|
|||
|
||||
pub fn register_group(
|
||||
&mut self,
|
||||
from_plugin: bool,
|
||||
is_loaded: bool,
|
||||
name: &'static str,
|
||||
deprecated_name: Option<&'static str>,
|
||||
to: Vec<LintId>,
|
||||
) {
|
||||
let new = self
|
||||
.lint_groups
|
||||
.insert(name, LintGroup { lint_ids: to, from_plugin, depr: None })
|
||||
.insert(name, LintGroup { lint_ids: to, is_loaded, depr: None })
|
||||
.is_none();
|
||||
if let Some(deprecated) = deprecated_name {
|
||||
self.lint_groups.insert(
|
||||
deprecated,
|
||||
LintGroup {
|
||||
lint_ids: vec![],
|
||||
from_plugin,
|
||||
is_loaded,
|
||||
depr: Some(LintAlias { name, silent: false }),
|
||||
},
|
||||
);
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
//! all other analyses. The `LintPass`es built into rustc are defined
|
||||
//! within [rustc_session::lint::builtin],
|
||||
//! which has further comments on how to add such a lint.
|
||||
//! rustc can also load user-defined lint plugins via the plugin mechanism.
|
||||
//! rustc can also load external lint plugins, as is done for Clippy.
|
||||
//!
|
||||
//! Some of rustc's lints are defined elsewhere in the compiler and work by
|
||||
//! calling `add_lint()` on the overall `Session` object. This works when
|
||||
|
|
|
@ -321,7 +321,7 @@ pub struct Lint {
|
|||
|
||||
pub future_incompatible: Option<FutureIncompatibleInfo>,
|
||||
|
||||
pub is_plugin: bool,
|
||||
pub is_loaded: bool,
|
||||
|
||||
/// `Some` if this lint is feature gated, otherwise `None`.
|
||||
pub feature_gate: Option<Symbol>,
|
||||
|
@ -399,7 +399,7 @@ impl Lint {
|
|||
default_level: Level::Forbid,
|
||||
desc: "",
|
||||
edition_lint_opts: None,
|
||||
is_plugin: false,
|
||||
is_loaded: false,
|
||||
report_in_external_macro: false,
|
||||
future_incompatible: None,
|
||||
feature_gate: None,
|
||||
|
@ -735,7 +735,7 @@ macro_rules! declare_lint {
|
|||
name: stringify!($NAME),
|
||||
default_level: $crate::$Level,
|
||||
desc: $desc,
|
||||
is_plugin: false,
|
||||
is_loaded: false,
|
||||
$($v: true,)*
|
||||
$(feature_gate: Some($gate),)?
|
||||
$(future_incompatible: Some($crate::FutureIncompatibleInfo {
|
||||
|
@ -777,7 +777,7 @@ macro_rules! declare_tool_lint {
|
|||
edition_lint_opts: None,
|
||||
report_in_external_macro: $external,
|
||||
future_incompatible: None,
|
||||
is_plugin: true,
|
||||
is_loaded: true,
|
||||
$(feature_gate: Some($gate),)?
|
||||
crate_level_only: false,
|
||||
..$crate::Lint::default_fields_for_macro()
|
||||
|
|
|
@ -196,9 +196,6 @@ metadata_newer_crate_version =
|
|||
metadata_no_crate_with_triple =
|
||||
couldn't find crate `{$crate_name}` with expected target triple {$locator_triple}{$add_info}
|
||||
|
||||
metadata_no_dylib_plugin =
|
||||
plugin `{$crate_name}` only found in rlib format, but must be available in dylib format
|
||||
|
||||
metadata_no_link_mod_override =
|
||||
overriding linking modifiers from command line is not supported
|
||||
|
||||
|
|
|
@ -682,14 +682,6 @@ impl IntoDiagnostic<'_> for CannotFindCrate {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_no_dylib_plugin, code = "E0457")]
|
||||
pub struct NoDylibPlugin {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub crate_name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_crate_location_unknown_type)]
|
||||
pub struct CrateLocationUnknownType<'a> {
|
||||
|
|
|
@ -220,7 +220,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
|||
use rustc_data_structures::memmap::Mmap;
|
||||
use rustc_data_structures::owned_slice::slice_owned;
|
||||
use rustc_data_structures::svh::Svh;
|
||||
use rustc_errors::{DiagnosticArgValue, FatalError, IntoDiagnosticArg};
|
||||
use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
|
||||
use rustc_fs_util::try_canonicalize;
|
||||
use rustc_session::config;
|
||||
use rustc_session::cstore::{CrateSource, MetadataLoader};
|
||||
|
@ -857,46 +857,6 @@ fn get_metadata_section<'p>(
|
|||
}
|
||||
}
|
||||
|
||||
/// Look for a plugin registrar. Returns its library path and crate disambiguator.
|
||||
pub fn find_plugin_registrar(
|
||||
sess: &Session,
|
||||
metadata_loader: &dyn MetadataLoader,
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
) -> PathBuf {
|
||||
find_plugin_registrar_impl(sess, metadata_loader, name).unwrap_or_else(|err| {
|
||||
// `core` is always available if we got as far as loading plugins.
|
||||
err.report(sess, span, false);
|
||||
FatalError.raise()
|
||||
})
|
||||
}
|
||||
|
||||
fn find_plugin_registrar_impl<'a>(
|
||||
sess: &'a Session,
|
||||
metadata_loader: &dyn MetadataLoader,
|
||||
name: Symbol,
|
||||
) -> Result<PathBuf, CrateError> {
|
||||
info!("find plugin registrar `{}`", name);
|
||||
let mut locator = CrateLocator::new(
|
||||
sess,
|
||||
metadata_loader,
|
||||
name,
|
||||
false, // is_rlib
|
||||
None, // hash
|
||||
None, // extra_filename
|
||||
true, // is_host
|
||||
PathKind::Crate,
|
||||
);
|
||||
|
||||
match locator.maybe_load_library_crate()? {
|
||||
Some(library) => match library.source.dylib {
|
||||
Some(dylib) => Ok(dylib.0),
|
||||
None => Err(CrateError::NonDylibPlugin(name)),
|
||||
},
|
||||
None => Err(locator.into_error(None)),
|
||||
}
|
||||
}
|
||||
|
||||
/// A diagnostic function for dumping crate metadata to an output stream.
|
||||
pub fn list_file_metadata(
|
||||
target: &Target,
|
||||
|
@ -964,7 +924,6 @@ pub(crate) enum CrateError {
|
|||
DlOpen(String),
|
||||
DlSym(String),
|
||||
LocatorCombined(Box<CombinedLocatorError>),
|
||||
NonDylibPlugin(Symbol),
|
||||
NotFound(Symbol),
|
||||
}
|
||||
|
||||
|
@ -1134,9 +1093,6 @@ impl CrateError {
|
|||
});
|
||||
}
|
||||
}
|
||||
CrateError::NonDylibPlugin(crate_name) => {
|
||||
sess.emit_err(errors::NoDylibPlugin { span, crate_name });
|
||||
}
|
||||
CrateError::NotFound(crate_name) => {
|
||||
sess.emit_err(errors::CannotFindCrate {
|
||||
span,
|
||||
|
|
|
@ -69,6 +69,7 @@ macro_rules! arena_types {
|
|||
[] dtorck_constraint: rustc_middle::traits::query::DropckConstraint<'tcx>,
|
||||
[] candidate_step: rustc_middle::traits::query::CandidateStep<'tcx>,
|
||||
[] autoderef_bad_ty: rustc_middle::traits::query::MethodAutoderefBadTy<'tcx>,
|
||||
[] canonical_goal_evaluation: rustc_middle::traits::solve::inspect::GoalEvaluationStep<'tcx>,
|
||||
[] query_region_constraints: rustc_middle::infer::canonical::QueryRegionConstraints<'tcx>,
|
||||
[] type_op_subtype:
|
||||
rustc_middle::infer::canonical::Canonical<'tcx,
|
||||
|
|
|
@ -66,7 +66,7 @@ macro_rules! declare_hooks {
|
|||
declare_hooks! {
|
||||
/// Tries to destructure an `mir::Const` ADT or array into its variant index
|
||||
/// and its field values. This should only be used for pretty printing.
|
||||
hook try_destructure_mir_constant_for_diagnostics(val: mir::ConstValue<'tcx>, ty: Ty<'tcx>) -> Option<mir::DestructuredConstant<'tcx>>;
|
||||
hook try_destructure_mir_constant_for_user_output(val: mir::ConstValue<'tcx>, ty: Ty<'tcx>) -> Option<mir::DestructuredConstant<'tcx>>;
|
||||
|
||||
/// Getting a &core::panic::Location referring to a span.
|
||||
hook const_caller_location(file: rustc_span::Symbol, line: u32, col: u32) -> mir::ConstValue<'tcx>;
|
||||
|
|
|
@ -9,17 +9,15 @@ use rustc_session::lint::{
|
|||
FutureIncompatibilityReason, Level, Lint, LintId,
|
||||
};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::hygiene::MacroKind;
|
||||
use rustc_span::source_map::{DesugaringKind, ExpnKind};
|
||||
use rustc_span::{symbol, Span, Symbol, DUMMY_SP};
|
||||
use rustc_span::hygiene::{ExpnKind, MacroKind};
|
||||
use rustc_span::{symbol, DesugaringKind, Span, Symbol, DUMMY_SP};
|
||||
|
||||
use crate::ty::TyCtxt;
|
||||
|
||||
/// How a lint level was set.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, HashStable, Debug)]
|
||||
pub enum LintLevelSource {
|
||||
/// Lint is at the default level as declared
|
||||
/// in rustc or a plugin.
|
||||
/// Lint is at the default level as declared in rustc.
|
||||
Default,
|
||||
|
||||
/// Lint level was set by an attribute.
|
||||
|
|
|
@ -10,8 +10,8 @@ use rustc_hir::ItemId;
|
|||
use rustc_index::Idx;
|
||||
use rustc_query_system::ich::StableHashingContext;
|
||||
use rustc_session::config::OptLevel;
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::Span;
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
|
||||
|
|
|
@ -1713,7 +1713,7 @@ fn pretty_print_const_value_tcx<'tcx>(
|
|||
(_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_non_region_param() => {
|
||||
let ct = tcx.lift(ct).unwrap();
|
||||
let ty = tcx.lift(ty).unwrap();
|
||||
if let Some(contents) = tcx.try_destructure_mir_constant_for_diagnostics(ct, ty) {
|
||||
if let Some(contents) = tcx.try_destructure_mir_constant_for_user_output(ct, ty) {
|
||||
let fields: Vec<(ConstValue<'_>, Ty<'_>)> = contents.fields.to_vec();
|
||||
match *ty.kind() {
|
||||
ty::Array(..) => {
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::infer::canonical::{Canonical, QueryResponse};
|
|||
use crate::ty::error::TypeError;
|
||||
use crate::ty::GenericArg;
|
||||
use crate::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::Span;
|
||||
|
||||
pub mod type_op {
|
||||
use crate::ty::fold::TypeFoldable;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::{CanonicalInput, QueryResult};
|
||||
use super::{inspect, CanonicalInput, QueryResult};
|
||||
use crate::ty::TyCtxt;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::sync::Lock;
|
||||
|
@ -14,8 +14,10 @@ pub struct EvaluationCache<'tcx> {
|
|||
map: Lock<FxHashMap<CanonicalInput<'tcx>, CacheEntry<'tcx>>>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct CacheData<'tcx> {
|
||||
pub result: QueryResult<'tcx>,
|
||||
pub proof_tree: Option<&'tcx [inspect::GoalEvaluationStep<'tcx>]>,
|
||||
pub reached_depth: usize,
|
||||
pub encountered_overflow: bool,
|
||||
}
|
||||
|
@ -24,22 +26,33 @@ impl<'tcx> EvaluationCache<'tcx> {
|
|||
/// Insert a final result into the global cache.
|
||||
pub fn insert(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
key: CanonicalInput<'tcx>,
|
||||
proof_tree: Option<&'tcx [inspect::GoalEvaluationStep<'tcx>]>,
|
||||
reached_depth: usize,
|
||||
did_overflow: bool,
|
||||
encountered_overflow: bool,
|
||||
cycle_participants: FxHashSet<CanonicalInput<'tcx>>,
|
||||
dep_node: DepNodeIndex,
|
||||
result: QueryResult<'tcx>,
|
||||
) {
|
||||
let mut map = self.map.borrow_mut();
|
||||
let entry = map.entry(key).or_default();
|
||||
let data = WithDepNode::new(dep_node, result);
|
||||
let data = WithDepNode::new(dep_node, QueryData { result, proof_tree });
|
||||
entry.cycle_participants.extend(cycle_participants);
|
||||
if did_overflow {
|
||||
if encountered_overflow {
|
||||
entry.with_overflow.insert(reached_depth, data);
|
||||
} else {
|
||||
entry.success = Some(Success { data, reached_depth });
|
||||
}
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
drop(map);
|
||||
if Some(CacheData { result, proof_tree, reached_depth, encountered_overflow })
|
||||
!= self.get(tcx, key, |_| false, Limit(reached_depth))
|
||||
{
|
||||
bug!("unable to retrieve inserted element from cache: {key:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to fetch a cached result, checking the recursion limit
|
||||
|
@ -62,27 +75,39 @@ impl<'tcx> EvaluationCache<'tcx> {
|
|||
|
||||
if let Some(ref success) = entry.success {
|
||||
if available_depth.value_within_limit(success.reached_depth) {
|
||||
let QueryData { result, proof_tree } = success.data.get(tcx);
|
||||
return Some(CacheData {
|
||||
result: success.data.get(tcx),
|
||||
result,
|
||||
proof_tree,
|
||||
reached_depth: success.reached_depth,
|
||||
encountered_overflow: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
entry.with_overflow.get(&available_depth.0).map(|e| CacheData {
|
||||
result: e.get(tcx),
|
||||
reached_depth: available_depth.0,
|
||||
encountered_overflow: true,
|
||||
entry.with_overflow.get(&available_depth.0).map(|e| {
|
||||
let QueryData { result, proof_tree } = e.get(tcx);
|
||||
CacheData {
|
||||
result,
|
||||
proof_tree,
|
||||
reached_depth: available_depth.0,
|
||||
encountered_overflow: true,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct Success<'tcx> {
|
||||
data: WithDepNode<QueryResult<'tcx>>,
|
||||
data: WithDepNode<QueryData<'tcx>>,
|
||||
reached_depth: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct QueryData<'tcx> {
|
||||
pub result: QueryResult<'tcx>,
|
||||
pub proof_tree: Option<&'tcx [inspect::GoalEvaluationStep<'tcx>]>,
|
||||
}
|
||||
|
||||
/// The cache entry for a goal `CanonicalInput`.
|
||||
///
|
||||
/// This contains results whose computation never hit the
|
||||
|
@ -96,5 +121,5 @@ struct CacheEntry<'tcx> {
|
|||
/// See the doc comment of `StackEntry::cycle_participants` for more
|
||||
/// details.
|
||||
cycle_participants: FxHashSet<CanonicalInput<'tcx>>,
|
||||
with_overflow: FxHashMap<usize, WithDepNode<QueryResult<'tcx>>>,
|
||||
with_overflow: FxHashMap<usize, WithDepNode<QueryData<'tcx>>>,
|
||||
}
|
||||
|
|
|
@ -42,12 +42,6 @@ pub struct State<'tcx, T> {
|
|||
|
||||
pub type CanonicalState<'tcx, T> = Canonical<'tcx, State<'tcx, T>>;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum CacheHit {
|
||||
Provisional,
|
||||
Global,
|
||||
}
|
||||
|
||||
/// When evaluating the root goals we also store the
|
||||
/// original values for the `CanonicalVarValues` of the
|
||||
/// canonicalized goal. We use this to map any [CanonicalState]
|
||||
|
@ -78,8 +72,8 @@ pub struct CanonicalGoalEvaluation<'tcx> {
|
|||
#[derive(Eq, PartialEq)]
|
||||
pub enum CanonicalGoalEvaluationKind<'tcx> {
|
||||
Overflow,
|
||||
CacheHit(CacheHit),
|
||||
Uncached { revisions: Vec<GoalEvaluationStep<'tcx>> },
|
||||
CycleInStack,
|
||||
Evaluation { revisions: &'tcx [GoalEvaluationStep<'tcx>] },
|
||||
}
|
||||
impl Debug for GoalEvaluation<'_> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
|
|
|
@ -74,13 +74,10 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
|
|||
CanonicalGoalEvaluationKind::Overflow => {
|
||||
writeln!(self.f, "OVERFLOW: {:?}", eval.result)
|
||||
}
|
||||
CanonicalGoalEvaluationKind::CacheHit(CacheHit::Global) => {
|
||||
writeln!(self.f, "GLOBAL CACHE HIT: {:?}", eval.result)
|
||||
CanonicalGoalEvaluationKind::CycleInStack => {
|
||||
writeln!(self.f, "CYCLE IN STACK: {:?}", eval.result)
|
||||
}
|
||||
CanonicalGoalEvaluationKind::CacheHit(CacheHit::Provisional) => {
|
||||
writeln!(self.f, "PROVISIONAL CACHE HIT: {:?}", eval.result)
|
||||
}
|
||||
CanonicalGoalEvaluationKind::Uncached { revisions } => {
|
||||
CanonicalGoalEvaluationKind::Evaluation { revisions } => {
|
||||
for (n, step) in revisions.iter().enumerate() {
|
||||
writeln!(self.f, "REVISION {n}")?;
|
||||
self.nested(|this| this.format_evaluation_step(step))?;
|
||||
|
|
|
@ -1107,8 +1107,10 @@ impl<'tcx> Ty<'tcx> {
|
|||
// This doesn't depend on regions, so try to minimize distinct
|
||||
// query keys used.
|
||||
// If normalization fails, we just use `query_ty`.
|
||||
let query_ty =
|
||||
tcx.try_normalize_erasing_regions(param_env, query_ty).unwrap_or(query_ty);
|
||||
debug_assert!(!param_env.has_infer());
|
||||
let query_ty = tcx
|
||||
.try_normalize_erasing_regions(param_env, query_ty)
|
||||
.unwrap_or_else(|_| tcx.erase_regions(query_ty));
|
||||
|
||||
tcx.needs_drop_raw(param_env.and(query_ty))
|
||||
}
|
||||
|
@ -1297,7 +1299,6 @@ pub fn needs_drop_components<'tcx>(
|
|||
| ty::FnDef(..)
|
||||
| ty::FnPtr(_)
|
||||
| ty::Char
|
||||
| ty::CoroutineWitness(..)
|
||||
| ty::RawPtr(_)
|
||||
| ty::Ref(..)
|
||||
| ty::Str => Ok(SmallVec::new()),
|
||||
|
@ -1337,7 +1338,8 @@ pub fn needs_drop_components<'tcx>(
|
|||
| ty::Placeholder(..)
|
||||
| ty::Infer(_)
|
||||
| ty::Closure(..)
|
||||
| ty::Coroutine(..) => Ok(smallvec![ty]),
|
||||
| ty::Coroutine(..)
|
||||
| ty::CoroutineWitness(..) => Ok(smallvec![ty]),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -856,7 +856,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
}
|
||||
|
||||
PatKind::InlineConstant { ref subpattern, .. } => {
|
||||
self.visit_primary_bindings(subpattern, pattern_user_ty.clone(), f)
|
||||
self.visit_primary_bindings(subpattern, pattern_user_ty, f)
|
||||
}
|
||||
|
||||
PatKind::Leaf { ref subpatterns } => {
|
||||
|
|
|
@ -186,8 +186,9 @@ use rustc_middle::{middle::codegen_fn_attrs::CodegenFnAttrFlags, mir::visit::TyC
|
|||
use rustc_session::config::EntryFnType;
|
||||
use rustc_session::lint::builtin::LARGE_ASSIGNMENTS;
|
||||
use rustc_session::Limit;
|
||||
use rustc_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP};
|
||||
use rustc_span::source_map::{dummy_spanned, respan, Spanned};
|
||||
use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_target::abi::Size;
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
|
|
@ -526,6 +526,9 @@ parse_missing_fn_for_function_definition = missing `fn` for function definition
|
|||
parse_missing_fn_for_method_definition = missing `fn` for method definition
|
||||
.suggestion = add `fn` here to parse `{$ident}` as a public method
|
||||
|
||||
parse_missing_fn_params = missing parameters for function definition
|
||||
.suggestion = add a parameter list
|
||||
|
||||
parse_missing_for_in_trait_impl = missing `for` in a trait impl
|
||||
.suggestion = add `for` here
|
||||
|
||||
|
|
|
@ -1551,6 +1551,14 @@ pub(crate) enum AmbiguousMissingKwForItemSub {
|
|||
HelpMacro,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_missing_fn_params)]
|
||||
pub(crate) struct MissingFnParams {
|
||||
#[primary_span]
|
||||
#[suggestion(code = "()", applicability = "machine-applicable", style = "short")]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_missing_trait_in_trait_impl)]
|
||||
pub(crate) struct MissingTraitInTraitImpl {
|
||||
|
|
|
@ -32,10 +32,10 @@ use rustc_macros::Subdiagnostic;
|
|||
use rustc_session::errors::{report_lit_error, ExprParenthesesNeeded};
|
||||
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
|
||||
use rustc_session::lint::BuiltinLintDiagnostics;
|
||||
use rustc_span::source_map::{self, Span, Spanned};
|
||||
use rustc_span::source_map::{self, Spanned};
|
||||
use rustc_span::symbol::kw::PathRoot;
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::{BytePos, Pos};
|
||||
use rustc_span::{BytePos, Pos, Span};
|
||||
use thin_vec::{thin_vec, ThinVec};
|
||||
|
||||
/// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression
|
||||
|
|
|
@ -22,9 +22,9 @@ use rustc_errors::{
|
|||
};
|
||||
use rustc_span::edit_distance::edit_distance;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::source_map::{self, Span};
|
||||
use rustc_span::source_map;
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use std::fmt::Write;
|
||||
use std::mem;
|
||||
use thin_vec::{thin_vec, ThinVec};
|
||||
|
@ -2499,6 +2499,16 @@ impl<'a> Parser<'a> {
|
|||
pub(super) fn parse_fn_params(&mut self, req_name: ReqName) -> PResult<'a, ThinVec<Param>> {
|
||||
let mut first_param = true;
|
||||
// Parse the arguments, starting out with `self` being allowed...
|
||||
if self.token.kind != TokenKind::OpenDelim(Delimiter::Parenthesis)
|
||||
// might be typo'd trait impl, handled elsewhere
|
||||
&& !self.token.is_keyword(kw::For)
|
||||
{
|
||||
// recover from missing argument list, e.g. `fn main -> () {}`
|
||||
self.sess
|
||||
.emit_err(errors::MissingFnParams { span: self.prev_token.span.shrink_to_hi() });
|
||||
return Ok(ThinVec::new());
|
||||
}
|
||||
|
||||
let (mut params, _) = self.parse_paren_comma_seq(|p| {
|
||||
p.recover_diff_marker();
|
||||
let snapshot = p.create_snapshot_for_diagnostic();
|
||||
|
|
|
@ -36,8 +36,8 @@ use rustc_errors::{
|
|||
Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, IntoDiagnostic, MultiSpan,
|
||||
};
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::source_map::{Span, DUMMY_SP};
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use std::ops::Range;
|
||||
use std::{mem, slice};
|
||||
use thin_vec::ThinVec;
|
||||
|
|
|
@ -20,8 +20,9 @@ use rustc_ast::{
|
|||
use rustc_ast_pretty::pprust;
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, PResult};
|
||||
use rustc_session::errors::ExprParenthesesNeeded;
|
||||
use rustc_span::source_map::{respan, Span, Spanned};
|
||||
use rustc_span::source_map::{respan, Spanned};
|
||||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::Span;
|
||||
use thin_vec::{thin_vec, ThinVec};
|
||||
|
||||
#[derive(PartialEq, Copy, Clone)]
|
||||
|
|
|
@ -10,8 +10,8 @@ use rustc_ast::{
|
|||
Path, PathSegment, QSelf,
|
||||
};
|
||||
use rustc_errors::{Applicability, IntoDiagnostic, PResult};
|
||||
use rustc_span::source_map::{BytePos, Span};
|
||||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::{BytePos, Span};
|
||||
use std::mem;
|
||||
use thin_vec::ThinVec;
|
||||
use tracing::debug;
|
||||
|
|
|
@ -20,8 +20,8 @@ use rustc_ast::{AttrStyle, AttrVec, LocalKind, MacCall, MacCallStmt, MacStmtStyl
|
|||
use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, HasAttrs, Local, Stmt};
|
||||
use rustc_ast::{StmtKind, DUMMY_NODE_ID};
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult};
|
||||
use rustc_span::source_map::{BytePos, Span};
|
||||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::{BytePos, Span};
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::mem;
|
||||
|
|
|
@ -18,9 +18,8 @@ use rustc_ast::{
|
|||
TraitObjectSyntax, Ty, TyKind,
|
||||
};
|
||||
use rustc_errors::{Applicability, PResult};
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::Symbol;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use thin_vec::{thin_vec, ThinVec};
|
||||
|
||||
/// Any `?`, `!`, or `~const` modifiers that appear at the start of a bound.
|
||||
|
|
|
@ -589,9 +589,6 @@ passes_pass_by_value =
|
|||
`pass_by_value` attribute should be applied to a struct, enum or type alias
|
||||
.label = is not a struct, enum or type alias
|
||||
|
||||
passes_plugin_registrar =
|
||||
`#[plugin_registrar]` only has an effect on functions
|
||||
|
||||
passes_proc_macro_bad_sig = {$kind} has incorrect signature
|
||||
|
||||
passes_repr_conflicting =
|
||||
|
|
|
@ -211,7 +211,6 @@ impl CheckAttrVisitor<'_> {
|
|||
sym::deprecated => self.check_deprecated(hir_id, attr, span, target),
|
||||
sym::macro_use | sym::macro_escape => self.check_macro_use(hir_id, attr, target),
|
||||
sym::path => self.check_generic_attr(hir_id, attr, target, Target::Mod),
|
||||
sym::plugin_registrar => self.check_plugin_registrar(hir_id, attr, target),
|
||||
sym::macro_export => self.check_macro_export(hir_id, attr, target),
|
||||
sym::ignore | sym::should_panic => {
|
||||
self.check_generic_attr(hir_id, attr, target, Target::Fn)
|
||||
|
@ -2237,17 +2236,6 @@ impl CheckAttrVisitor<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_plugin_registrar(&self, hir_id: HirId, attr: &Attribute, target: Target) {
|
||||
if target != Target::Fn {
|
||||
self.tcx.emit_spanned_lint(
|
||||
UNUSED_ATTRIBUTES,
|
||||
hir_id,
|
||||
attr.span,
|
||||
errors::PluginRegistrar,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_unused_attribute(&self, hir_id: HirId, attr: &Attribute) {
|
||||
// Warn on useless empty attributes.
|
||||
let note = if matches!(
|
||||
|
|
|
@ -717,10 +717,6 @@ pub enum MacroExport {
|
|||
TooManyItems,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(passes_plugin_registrar)]
|
||||
pub struct PluginRegistrar;
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub enum UnusedNote {
|
||||
#[note(passes_unused_empty_lints_note)]
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
[package]
|
||||
name = "rustc_plugin_impl"
|
||||
version = "0.0.0"
|
||||
build = false
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
libloading = "0.7.1"
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||
rustc_lint = { path = "../rustc_lint" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_metadata = { path = "../rustc_metadata" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
# tidy-alphabetical-end
|
|
@ -1,4 +0,0 @@
|
|||
plugin_impl_load_plugin_error = {$msg}
|
||||
|
||||
plugin_impl_malformed_plugin_attribute = malformed `plugin` attribute
|
||||
.label = malformed attribute
|
|
@ -1,20 +0,0 @@
|
|||
//! Errors emitted by plugin_impl
|
||||
|
||||
use rustc_macros::Diagnostic;
|
||||
use rustc_span::Span;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(plugin_impl_load_plugin_error)]
|
||||
pub struct LoadPluginError {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub msg: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(plugin_impl_malformed_plugin_attribute, code = "E0498")]
|
||||
pub struct MalformedPluginAttribute {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
//! Infrastructure for compiler plugins.
|
||||
//!
|
||||
//! Plugins are a deprecated way to extend the behavior of `rustc` in various ways.
|
||||
//!
|
||||
//! See the [`plugin`
|
||||
//! feature](https://doc.rust-lang.org/nightly/unstable-book/language-features/plugin.html)
|
||||
//! of the Unstable Book for some examples.
|
||||
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![cfg_attr(not(bootstrap), doc(rust_logo))]
|
||||
#![cfg_attr(not(bootstrap), feature(rustdoc_internals))]
|
||||
#![cfg_attr(not(bootstrap), allow(internal_features))]
|
||||
#![recursion_limit = "256"]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
|
||||
use rustc_fluent_macro::fluent_messages;
|
||||
use rustc_lint::LintStore;
|
||||
|
||||
mod errors;
|
||||
pub mod load;
|
||||
|
||||
fluent_messages! { "../messages.ftl" }
|
||||
|
||||
/// Structure used to register plugins.
|
||||
///
|
||||
/// A plugin registrar function takes an `&mut Registry` and should call
|
||||
/// methods to register its plugins.
|
||||
pub struct Registry<'a> {
|
||||
/// The `LintStore` allows plugins to register new lints.
|
||||
pub lint_store: &'a mut LintStore,
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
//! Used by `rustc` when loading a plugin.
|
||||
|
||||
use crate::errors::{LoadPluginError, MalformedPluginAttribute};
|
||||
use crate::Registry;
|
||||
use libloading::Library;
|
||||
use rustc_ast::Attribute;
|
||||
use rustc_metadata::locator;
|
||||
use rustc_session::cstore::MetadataLoader;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::symbol::{sym, Ident};
|
||||
|
||||
use std::env;
|
||||
use std::mem;
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// Pointer to a registrar function.
|
||||
type PluginRegistrarFn = fn(&mut Registry<'_>);
|
||||
|
||||
/// Read plugin metadata and dynamically load registrar functions.
|
||||
pub fn load_plugins(
|
||||
sess: &Session,
|
||||
metadata_loader: &dyn MetadataLoader,
|
||||
attrs: &[Attribute],
|
||||
) -> Vec<PluginRegistrarFn> {
|
||||
let mut plugins = Vec::new();
|
||||
|
||||
for attr in attrs {
|
||||
if !attr.has_name(sym::plugin) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for plugin in attr.meta_item_list().unwrap_or_default() {
|
||||
match plugin.ident() {
|
||||
Some(ident) if plugin.is_word() => {
|
||||
load_plugin(&mut plugins, sess, metadata_loader, ident)
|
||||
}
|
||||
_ => {
|
||||
sess.emit_err(MalformedPluginAttribute { span: plugin.span() });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plugins
|
||||
}
|
||||
|
||||
fn load_plugin(
|
||||
plugins: &mut Vec<PluginRegistrarFn>,
|
||||
sess: &Session,
|
||||
metadata_loader: &dyn MetadataLoader,
|
||||
ident: Ident,
|
||||
) {
|
||||
let lib = locator::find_plugin_registrar(sess, metadata_loader, ident.span, ident.name);
|
||||
let fun = dylink_registrar(lib).unwrap_or_else(|err| {
|
||||
// This is fatal: there are almost certainly macros we need inside this crate, so
|
||||
// continuing would spew "macro undefined" errors.
|
||||
sess.emit_fatal(LoadPluginError { span: ident.span, msg: err.to_string() });
|
||||
});
|
||||
plugins.push(fun);
|
||||
}
|
||||
|
||||
/// Dynamically link a registrar function into the compiler process.
|
||||
fn dylink_registrar(lib_path: PathBuf) -> Result<PluginRegistrarFn, libloading::Error> {
|
||||
// Make sure the path contains a / or the linker will search for it.
|
||||
let lib_path = env::current_dir().unwrap().join(&lib_path);
|
||||
|
||||
let lib = unsafe { Library::new(&lib_path) }?;
|
||||
|
||||
let registrar_sym = unsafe { lib.get::<PluginRegistrarFn>(b"__rustc_plugin_registrar") }?;
|
||||
|
||||
// Intentionally leak the dynamic library. We can't ever unload it
|
||||
// since the library can make things that will live arbitrarily long
|
||||
// (e.g., an Rc cycle or a thread).
|
||||
let registrar_sym = unsafe { registrar_sym.into_raw() };
|
||||
mem::forget(lib);
|
||||
|
||||
Ok(*registrar_sym)
|
||||
}
|
|
@ -18,10 +18,9 @@ use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS};
|
|||
|
||||
use rustc_feature::UnstableFeatures;
|
||||
use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_STABLE_EDITION};
|
||||
use rustc_span::source_map::{FileName, FilePathMapping};
|
||||
use rustc_span::source_map::FilePathMapping;
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_span::SourceFileHashAlgorithm;
|
||||
use rustc_span::{FileNameDisplayPreference, RealFileName};
|
||||
use rustc_span::{FileName, FileNameDisplayPreference, RealFileName, SourceFileHashAlgorithm};
|
||||
|
||||
use rustc_errors::emitter::HumanReadableErrorType;
|
||||
use rustc_errors::{ColorConfig, DiagnosticArgValue, HandlerFlags, IntoDiagnosticArg};
|
||||
|
@ -2674,28 +2673,19 @@ pub fn build_session_options(
|
|||
);
|
||||
}
|
||||
|
||||
// Handle both `-Z symbol-mangling-version` and `-C symbol-mangling-version`; the latter takes
|
||||
// precedence.
|
||||
match (cg.symbol_mangling_version, unstable_opts.symbol_mangling_version) {
|
||||
(Some(smv_c), Some(smv_z)) if smv_c != smv_z => {
|
||||
handler.early_error(
|
||||
"incompatible values passed for `-C symbol-mangling-version` \
|
||||
and `-Z symbol-mangling-version`",
|
||||
);
|
||||
// Check for unstable values of `-C symbol-mangling-version`.
|
||||
// This is what prevents them from being used on stable compilers.
|
||||
match cg.symbol_mangling_version {
|
||||
// Stable values:
|
||||
None | Some(SymbolManglingVersion::V0) => {}
|
||||
// Unstable values:
|
||||
Some(SymbolManglingVersion::Legacy) => {
|
||||
if !unstable_opts.unstable_options {
|
||||
handler.early_error(
|
||||
"`-C symbol-mangling-version=legacy` requires `-Z unstable-options`",
|
||||
);
|
||||
}
|
||||
}
|
||||
(Some(SymbolManglingVersion::V0), _) => {}
|
||||
(Some(_), _) if !unstable_opts.unstable_options => {
|
||||
handler
|
||||
.early_error("`-C symbol-mangling-version=legacy` requires `-Z unstable-options`");
|
||||
}
|
||||
(None, None) => {}
|
||||
(None, smv) => {
|
||||
handler.early_warn(
|
||||
"`-Z symbol-mangling-version` is deprecated; use `-C symbol-mangling-version`",
|
||||
);
|
||||
cg.symbol_mangling_version = smv;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// Check for unstable values of `-C instrument-coverage`.
|
||||
|
|
|
@ -1529,8 +1529,6 @@ options! {
|
|||
dump_solver_proof_tree: DumpSolverProofTree = (DumpSolverProofTree::Never, parse_dump_solver_proof_tree, [UNTRACKED],
|
||||
"dump a proof tree for every goal evaluated by the new trait solver. If the flag is specified without any options after it
|
||||
then it defaults to `always`. If the flag is not specified at all it defaults to `on-request`."),
|
||||
dump_solver_proof_tree_use_cache: Option<bool> = (None, parse_opt_bool, [UNTRACKED],
|
||||
"determines whether dumped proof trees use the global cache"),
|
||||
dwarf_version: Option<u32> = (None, parse_opt_number, [TRACKED],
|
||||
"version of DWARF debug information to emit (default: 2 or 4, depending on platform)"),
|
||||
dylib_lto: bool = (false, parse_bool, [UNTRACKED],
|
||||
|
@ -1823,9 +1821,6 @@ written to standard error output)"),
|
|||
"control if mem::uninitialized and mem::zeroed panic on more UB"),
|
||||
strip: Strip = (Strip::None, parse_strip, [UNTRACKED],
|
||||
"tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"),
|
||||
symbol_mangling_version: Option<SymbolManglingVersion> = (None,
|
||||
parse_symbol_mangling_version, [TRACKED],
|
||||
"which mangling version to use for symbol names ('legacy' (default) or 'v0')"),
|
||||
#[rustc_lint_opt_deny_field_access("use `Session::teach` instead of this field")]
|
||||
teach: bool = (false, parse_bool, [TRACKED],
|
||||
"show extended diagnostic help (default: no)"),
|
||||
|
|
|
@ -31,8 +31,8 @@ use rustc_errors::{
|
|||
use rustc_macros::HashStable_Generic;
|
||||
pub use rustc_span::def_id::StableCrateId;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMap, Span};
|
||||
use rustc_span::{SourceFileHashAlgorithm, Symbol};
|
||||
use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMap};
|
||||
use rustc_span::{SourceFileHashAlgorithm, Span, Symbol};
|
||||
use rustc_target::asm::InlineAsmArch;
|
||||
use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel};
|
||||
use rustc_target::spec::{
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
/// Used as a return value to signify a fatal error occurred. (It is also
|
||||
/// used as the argument to panic at the moment, but that will eventually
|
||||
/// not be true.)
|
||||
/// Used as a return value to signify a fatal error occurred.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[must_use]
|
||||
pub struct FatalError;
|
||||
|
||||
pub struct FatalErrorMarker;
|
||||
|
||||
// Don't implement Send on FatalError. This makes it impossible to panic!(FatalError).
|
||||
// Don't implement Send on FatalError. This makes it impossible to `panic_any!(FatalError)`.
|
||||
// We don't want to invoke the panic handler and print a backtrace for fatal errors.
|
||||
impl !Send for FatalError {}
|
||||
|
||||
|
|
|
@ -24,16 +24,13 @@
|
|||
// because getting it wrong can lead to nested `HygieneData::with` calls that
|
||||
// trigger runtime aborts. (Fortunately these are obvious and easy to fix.)
|
||||
|
||||
use crate::def_id::{CrateNum, DefId, StableCrateId, CRATE_DEF_ID, LOCAL_CRATE};
|
||||
use crate::edition::Edition;
|
||||
use crate::symbol::{kw, sym, Symbol};
|
||||
use crate::with_session_globals;
|
||||
use crate::{HashStableContext, Span, DUMMY_SP};
|
||||
|
||||
use crate::def_id::{CrateNum, DefId, StableCrateId, CRATE_DEF_ID, LOCAL_CRATE};
|
||||
use crate::{with_session_globals, HashStableContext, Span, DUMMY_SP};
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::stable_hasher::HashingControls;
|
||||
use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
|
||||
use rustc_data_structures::stable_hasher::{Hash64, HashStable, HashingControls, StableHasher};
|
||||
use rustc_data_structures::sync::{Lock, Lrc, WorkerLocal};
|
||||
use rustc_data_structures::unhash::UnhashMap;
|
||||
use rustc_index::IndexVec;
|
||||
|
@ -130,7 +127,7 @@ impl ExpnHash {
|
|||
|
||||
/// Returns the crate-local part of the [ExpnHash].
|
||||
///
|
||||
/// Used for tests.
|
||||
/// Used for assertions.
|
||||
#[inline]
|
||||
pub fn local_hash(self) -> Hash64 {
|
||||
self.0.split().1
|
||||
|
@ -173,7 +170,7 @@ impl LocalExpnId {
|
|||
pub const ROOT: LocalExpnId = LocalExpnId::from_u32(0);
|
||||
|
||||
#[inline]
|
||||
pub fn from_raw(idx: ExpnIndex) -> LocalExpnId {
|
||||
fn from_raw(idx: ExpnIndex) -> LocalExpnId {
|
||||
LocalExpnId::from_u32(idx.as_u32())
|
||||
}
|
||||
|
||||
|
@ -204,11 +201,6 @@ impl LocalExpnId {
|
|||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn expn_hash(self) -> ExpnHash {
|
||||
HygieneData::with(|data| data.local_expn_hash(self))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn expn_data(self) -> ExpnData {
|
||||
HygieneData::with(|data| data.local_expn_data(self).clone())
|
||||
|
@ -239,13 +231,6 @@ impl LocalExpnId {
|
|||
self.to_expn_id().is_descendant_of(ancestor.to_expn_id())
|
||||
}
|
||||
|
||||
/// `expn_id.outer_expn_is_descendant_of(ctxt)` is equivalent to but faster than
|
||||
/// `expn_id.is_descendant_of(ctxt.outer_expn())`.
|
||||
#[inline]
|
||||
pub fn outer_expn_is_descendant_of(self, ctxt: SyntaxContext) -> bool {
|
||||
self.to_expn_id().outer_expn_is_descendant_of(ctxt)
|
||||
}
|
||||
|
||||
/// Returns span for the macro which originally caused this expansion to happen.
|
||||
///
|
||||
/// Stops backtracing at include! boundary.
|
||||
|
@ -253,12 +238,6 @@ impl LocalExpnId {
|
|||
pub fn expansion_cause(self) -> Option<Span> {
|
||||
self.to_expn_id().expansion_cause()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[track_caller]
|
||||
pub fn parent(self) -> LocalExpnId {
|
||||
self.expn_data().parent.as_local().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl ExpnId {
|
||||
|
@ -333,7 +312,7 @@ impl ExpnId {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct HygieneData {
|
||||
pub(crate) struct HygieneData {
|
||||
/// Each expansion should have an associated expansion data, but sometimes there's a delay
|
||||
/// between creation of an expansion ID and obtaining its data (e.g. macros are collected
|
||||
/// first and then resolved later), so we use an `Option` here.
|
||||
|
@ -384,15 +363,10 @@ impl HygieneData {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn with<T, F: FnOnce(&mut HygieneData) -> T>(f: F) -> T {
|
||||
fn with<T, F: FnOnce(&mut HygieneData) -> T>(f: F) -> T {
|
||||
with_session_globals(|session_globals| f(&mut session_globals.hygiene_data.borrow_mut()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn local_expn_hash(&self, expn_id: LocalExpnId) -> ExpnHash {
|
||||
self.local_expn_hashes[expn_id]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn expn_hash(&self, expn_id: ExpnId) -> ExpnHash {
|
||||
match expn_id.as_local() {
|
||||
|
@ -746,7 +720,7 @@ impl SyntaxContext {
|
|||
}
|
||||
|
||||
/// Like `SyntaxContext::adjust`, but also normalizes `self` to macros 2.0.
|
||||
pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
|
||||
pub(crate) fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
|
||||
HygieneData::with(|data| {
|
||||
*self = data.normalize_to_macros_2_0(*self);
|
||||
data.adjust(self, expn_id)
|
||||
|
@ -779,7 +753,11 @@ impl SyntaxContext {
|
|||
/// ```
|
||||
/// This returns `None` if the context cannot be glob-adjusted.
|
||||
/// Otherwise, it returns the scope to use when privacy checking (see `adjust` for details).
|
||||
pub fn glob_adjust(&mut self, expn_id: ExpnId, glob_span: Span) -> Option<Option<ExpnId>> {
|
||||
pub(crate) fn glob_adjust(
|
||||
&mut self,
|
||||
expn_id: ExpnId,
|
||||
glob_span: Span,
|
||||
) -> Option<Option<ExpnId>> {
|
||||
HygieneData::with(|data| {
|
||||
let mut scope = None;
|
||||
let mut glob_ctxt = data.normalize_to_macros_2_0(glob_span.ctxt());
|
||||
|
@ -803,7 +781,7 @@ impl SyntaxContext {
|
|||
/// assert!(self.glob_adjust(expansion, glob_ctxt) == Some(privacy_checking_scope));
|
||||
/// }
|
||||
/// ```
|
||||
pub fn reverse_glob_adjust(
|
||||
pub(crate) fn reverse_glob_adjust(
|
||||
&mut self,
|
||||
expn_id: ExpnId,
|
||||
glob_span: Span,
|
||||
|
@ -858,11 +836,11 @@ impl SyntaxContext {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn outer_mark(self) -> (ExpnId, Transparency) {
|
||||
fn outer_mark(self) -> (ExpnId, Transparency) {
|
||||
HygieneData::with(|data| data.outer_mark(self))
|
||||
}
|
||||
|
||||
pub fn dollar_crate_name(self) -> Symbol {
|
||||
pub(crate) fn dollar_crate_name(self) -> Symbol {
|
||||
HygieneData::with(|data| data.syntax_context_data[self.0 as usize].dollar_crate_name)
|
||||
}
|
||||
|
||||
|
@ -961,12 +939,12 @@ pub struct ExpnData {
|
|||
/// The normal module (`mod`) in which the expanded macro was defined.
|
||||
pub parent_module: Option<DefId>,
|
||||
/// Suppresses the `unsafe_code` lint for code produced by this macro.
|
||||
pub allow_internal_unsafe: bool,
|
||||
pub(crate) allow_internal_unsafe: bool,
|
||||
/// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`) for this macro.
|
||||
pub local_inner_macros: bool,
|
||||
/// Should debuginfo for the macro be collapsed to the outermost expansion site (in other
|
||||
/// words, was the macro definition annotated with `#[collapse_debuginfo]`)?
|
||||
pub collapse_debuginfo: bool,
|
||||
pub(crate) collapse_debuginfo: bool,
|
||||
}
|
||||
|
||||
impl !PartialEq for ExpnData {}
|
||||
|
|
|
@ -4,10 +4,12 @@
|
|||
//!
|
||||
//! - the *span*, represented by [`SpanData`] and related types;
|
||||
//! - source code as represented by a [`SourceMap`]; and
|
||||
//! - interned strings, represented by [`Symbol`]s, with some common symbols available statically in the [`sym`] module.
|
||||
//! - interned strings, represented by [`Symbol`]s, with some common symbols available statically
|
||||
//! in the [`sym`] module.
|
||||
//!
|
||||
//! Unlike most compilers, the span contains not only the position in the source code, but also various other metadata,
|
||||
//! such as the edition and macro hygiene. This metadata is stored in [`SyntaxContext`] and [`ExpnData`].
|
||||
//! Unlike most compilers, the span contains not only the position in the source code, but also
|
||||
//! various other metadata, such as the edition and macro hygiene. This metadata is stored in
|
||||
//! [`SyntaxContext`] and [`ExpnData`].
|
||||
//!
|
||||
//! ## Note
|
||||
//!
|
||||
|
@ -117,7 +119,6 @@ impl SessionGlobals {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn create_session_globals_then<R>(edition: Edition, f: impl FnOnce() -> R) -> R {
|
||||
assert!(
|
||||
!SESSION_GLOBALS.is_set(),
|
||||
|
@ -128,7 +129,6 @@ pub fn create_session_globals_then<R>(edition: Edition, f: impl FnOnce() -> R) -
|
|||
SESSION_GLOBALS.set(&session_globals, f)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_session_globals_then<R>(session_globals: &SessionGlobals, f: impl FnOnce() -> R) -> R {
|
||||
assert!(
|
||||
!SESSION_GLOBALS.is_set(),
|
||||
|
@ -138,7 +138,6 @@ pub fn set_session_globals_then<R>(session_globals: &SessionGlobals, f: impl FnO
|
|||
SESSION_GLOBALS.set(session_globals, f)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn create_default_session_if_not_set_then<R, F>(f: F) -> R
|
||||
where
|
||||
F: FnOnce(&SessionGlobals) -> R,
|
||||
|
@ -146,7 +145,6 @@ where
|
|||
create_session_if_not_set_then(edition::DEFAULT_EDITION, f)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn create_session_if_not_set_then<R, F>(edition: Edition, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&SessionGlobals) -> R,
|
||||
|
@ -159,7 +157,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn with_session_globals<R, F>(f: F) -> R
|
||||
where
|
||||
F: FnOnce(&SessionGlobals) -> R,
|
||||
|
@ -167,7 +164,6 @@ where
|
|||
SESSION_GLOBALS.with(f)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn create_default_session_globals_then<R>(f: impl FnOnce() -> R) -> R {
|
||||
create_session_globals_then(edition::DEFAULT_EDITION, f)
|
||||
}
|
||||
|
@ -179,8 +175,7 @@ scoped_tls::scoped_thread_local!(static SESSION_GLOBALS: SessionGlobals);
|
|||
|
||||
// FIXME: We should use this enum or something like it to get rid of the
|
||||
// use of magic `/rust/1.x/...` paths across the board.
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd)]
|
||||
#[derive(Decodable)]
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Decodable)]
|
||||
pub enum RealFileName {
|
||||
LocalPath(PathBuf),
|
||||
/// For remapped paths (namely paths into libstd that have been mapped
|
||||
|
@ -217,8 +212,8 @@ impl<S: Encoder> Encodable<S> for RealFileName {
|
|||
|
||||
RealFileName::Remapped { ref local_path, ref virtual_name } => encoder
|
||||
.emit_enum_variant(1, |encoder| {
|
||||
// For privacy and build reproducibility, we must not embed host-dependant path in artifacts
|
||||
// if they have been remapped by --remap-path-prefix
|
||||
// For privacy and build reproducibility, we must not embed host-dependant path
|
||||
// in artifacts if they have been remapped by --remap-path-prefix
|
||||
assert!(local_path.is_none());
|
||||
local_path.encode(encoder);
|
||||
virtual_name.encode(encoder);
|
||||
|
@ -954,7 +949,7 @@ impl Span {
|
|||
/// Produces a span with the same location as `self` and context produced by a macro with the
|
||||
/// given ID and transparency, assuming that macro was defined directly and not produced by
|
||||
/// some other macro (which is the case for built-in and procedural macros).
|
||||
pub fn with_ctxt_from_mark(self, expn_id: ExpnId, transparency: Transparency) -> Span {
|
||||
fn with_ctxt_from_mark(self, expn_id: ExpnId, transparency: Transparency) -> Span {
|
||||
self.with_ctxt(SyntaxContext::root().apply_mark(expn_id, transparency))
|
||||
}
|
||||
|
||||
|
@ -1529,7 +1524,8 @@ impl SourceFile {
|
|||
})
|
||||
}
|
||||
|
||||
/// This converts the `lines` field to contain `SourceFileLines::Lines` if needed and freezes it.
|
||||
/// This converts the `lines` field to contain `SourceFileLines::Lines` if needed and freezes
|
||||
/// it.
|
||||
fn convert_diffs_to_lines_frozen(&self) {
|
||||
let mut guard = if let Some(guard) = self.lines.try_write() { guard } else { return };
|
||||
|
||||
|
@ -2247,6 +2243,9 @@ where
|
|||
|
||||
/// Useful type to use with `Result<>` indicate that an error has already
|
||||
/// been reported to the user, so no need to continue checking.
|
||||
///
|
||||
/// The `()` field is necessary: it is non-`pub`, which means values of this
|
||||
/// type cannot be constructed outside of this crate.
|
||||
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(HashStable_Generic)]
|
||||
pub struct ErrorGuaranteed(());
|
||||
|
@ -2264,7 +2263,8 @@ impl<E: rustc_serialize::Encoder> Encodable<E> for ErrorGuaranteed {
|
|||
#[inline]
|
||||
fn encode(&self, _e: &mut E) {
|
||||
panic!(
|
||||
"should never serialize an `ErrorGuaranteed`, as we do not write metadata or incremental caches in case errors occurred"
|
||||
"should never serialize an `ErrorGuaranteed`, as we do not write metadata or \
|
||||
incremental caches in case errors occurred"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,20 +9,15 @@
|
|||
//! within the `SourceMap`, which upon request can be converted to line and column
|
||||
//! information, source code snippets, etc.
|
||||
|
||||
pub use crate::hygiene::{ExpnData, ExpnKind};
|
||||
pub use crate::*;
|
||||
|
||||
use crate::*;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::stable_hasher::{Hash128, Hash64, StableHasher};
|
||||
use rustc_data_structures::sync::{IntoDynSyncSend, Lrc, MappedReadGuard, ReadGuard, RwLock};
|
||||
use std::cmp;
|
||||
use std::hash::Hash;
|
||||
use std::path::{self, Path, PathBuf};
|
||||
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::io::BorrowedBuf;
|
||||
use std::io::Read;
|
||||
use std::hash::Hash;
|
||||
use std::io::{self, BorrowedBuf, Read};
|
||||
use std::path::{self, Path, PathBuf};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
@ -41,7 +36,7 @@ pub fn original_sp(sp: Span, enclosing_sp: Span) -> Span {
|
|||
}
|
||||
}
|
||||
|
||||
pub mod monotonic {
|
||||
mod monotonic {
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
/// A `MonotonicVec` is a `Vec` which can only be grown.
|
||||
|
@ -51,18 +46,14 @@ pub mod monotonic {
|
|||
// field is inaccessible
|
||||
pub struct MonotonicVec<T>(Vec<T>);
|
||||
impl<T> MonotonicVec<T> {
|
||||
pub fn new(val: Vec<T>) -> MonotonicVec<T> {
|
||||
MonotonicVec(val)
|
||||
}
|
||||
|
||||
pub fn push(&mut self, val: T) {
|
||||
pub(super) fn push(&mut self, val: T) {
|
||||
self.0.push(val);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Default for MonotonicVec<T> {
|
||||
fn default() -> Self {
|
||||
MonotonicVec::new(vec![])
|
||||
MonotonicVec(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -207,7 +198,7 @@ impl StableSourceFileId {
|
|||
//
|
||||
|
||||
#[derive(Default)]
|
||||
pub(super) struct SourceMapFiles {
|
||||
struct SourceMapFiles {
|
||||
source_files: monotonic::MonotonicVec<Lrc<SourceFile>>,
|
||||
stable_id_to_source_file: FxHashMap<StableSourceFileId, Lrc<SourceFile>>,
|
||||
}
|
||||
|
@ -466,33 +457,6 @@ impl SourceMap {
|
|||
self.span_to_string(sp, FileNameDisplayPreference::Remapped)
|
||||
}
|
||||
|
||||
/// Format the span location suitable for pretty printing annotations with relative line numbers
|
||||
pub fn span_to_relative_line_string(&self, sp: Span, relative_to: Span) -> String {
|
||||
if self.files.borrow().source_files.is_empty() || sp.is_dummy() || relative_to.is_dummy() {
|
||||
return "no-location".to_string();
|
||||
}
|
||||
|
||||
let lo = self.lookup_char_pos(sp.lo());
|
||||
let hi = self.lookup_char_pos(sp.hi());
|
||||
let offset = self.lookup_char_pos(relative_to.lo());
|
||||
|
||||
if lo.file.name != offset.file.name || !relative_to.contains(sp) {
|
||||
return self.span_to_embeddable_string(sp);
|
||||
}
|
||||
|
||||
let lo_line = lo.line.saturating_sub(offset.line);
|
||||
let hi_line = hi.line.saturating_sub(offset.line);
|
||||
|
||||
format!(
|
||||
"{}:+{}:{}: +{}:{}",
|
||||
lo.file.name.display(FileNameDisplayPreference::Remapped),
|
||||
lo_line,
|
||||
lo.col.to_usize() + 1,
|
||||
hi_line,
|
||||
hi.col.to_usize() + 1,
|
||||
)
|
||||
}
|
||||
|
||||
/// Format the span location to be printed in diagnostics. Must not be emitted
|
||||
/// to build artifacts as this may leak local file paths. Use span_to_embeddable_string
|
||||
/// for string suitable for embedding.
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
//! type, and vice versa.
|
||||
|
||||
use rustc_arena::DroplessArena;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
|
||||
use rustc_data_structures::sync::Lock;
|
||||
use rustc_macros::HashStable_Generic;
|
||||
|
@ -20,8 +20,8 @@ mod tests;
|
|||
|
||||
// The proc macro code for this is in `compiler/rustc_macros/src/symbols.rs`.
|
||||
symbols! {
|
||||
// After modifying this list adjust `is_special`, `is_used_keyword`/`is_unused_keyword`,
|
||||
// this should be rarely necessary though if the keywords are kept in alphabetic order.
|
||||
// If you modify this list, adjust `is_special` and `is_used_keyword`/`is_unused_keyword`.
|
||||
// But this should rarely be necessary if the keywords are kept in alphabetic order.
|
||||
Keywords {
|
||||
// Special reserved identifiers used internally for elided lifetimes,
|
||||
// unnamed method parameters, crate root module, error recovery etc.
|
||||
|
@ -316,6 +316,7 @@ symbols! {
|
|||
ToOwned,
|
||||
ToString,
|
||||
TokenStream,
|
||||
Trait,
|
||||
Try,
|
||||
TryCaptureGeneric,
|
||||
TryCapturePrintable,
|
||||
|
@ -893,7 +894,7 @@ symbols! {
|
|||
inline_const_pat,
|
||||
inout,
|
||||
instruction_set,
|
||||
integer_: "integer",
|
||||
integer_: "integer", // underscore to avoid clashing with the function `sym::integer` below
|
||||
integral,
|
||||
into_future,
|
||||
into_iter,
|
||||
|
@ -2076,43 +2077,33 @@ impl<CTX> ToStableHashKey<CTX> for Symbol {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct Interner(Lock<InternerInner>);
|
||||
|
||||
// The `&'static str`s in this type actually point into the arena.
|
||||
//
|
||||
// The `FxHashMap`+`Vec` pair could be replaced by `FxIndexSet`, but #75278
|
||||
// found that to regress performance up to 2% in some cases. This might be
|
||||
// revisited after further improvements to `indexmap`.
|
||||
//
|
||||
// This type is private to prevent accidentally constructing more than one
|
||||
// `Interner` on the same thread, which makes it easy to mix up `Symbol`s
|
||||
// between `Interner`s.
|
||||
#[derive(Default)]
|
||||
struct InternerInner {
|
||||
arena: DroplessArena,
|
||||
names: FxHashMap<&'static str, Symbol>,
|
||||
strings: Vec<&'static str>,
|
||||
strings: FxIndexSet<&'static str>,
|
||||
}
|
||||
|
||||
impl Interner {
|
||||
fn prefill(init: &[&'static str]) -> Self {
|
||||
Interner(Lock::new(InternerInner {
|
||||
strings: init.into(),
|
||||
names: init.iter().copied().zip((0..).map(Symbol::new)).collect(),
|
||||
..Default::default()
|
||||
arena: Default::default(),
|
||||
strings: init.iter().copied().collect(),
|
||||
}))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn intern(&self, string: &str) -> Symbol {
|
||||
let mut inner = self.0.lock();
|
||||
if let Some(&name) = inner.names.get(string) {
|
||||
return name;
|
||||
if let Some(idx) = inner.strings.get_index_of(string) {
|
||||
return Symbol::new(idx as u32);
|
||||
}
|
||||
|
||||
let name = Symbol::new(inner.strings.len() as u32);
|
||||
|
||||
// SAFETY: we convert from `&str` to `&[u8]`, clone it into the arena,
|
||||
// and immediately convert the clone back to `&[u8]`, all because there
|
||||
// is no `inner.arena.alloc_str()` method. This is clearly safe.
|
||||
|
@ -2122,20 +2113,21 @@ impl Interner {
|
|||
// SAFETY: we can extend the arena allocation to `'static` because we
|
||||
// only access these while the arena is still alive.
|
||||
let string: &'static str = unsafe { &*(string as *const str) };
|
||||
inner.strings.push(string);
|
||||
|
||||
// This second hash table lookup can be avoided by using `RawEntryMut`,
|
||||
// but this code path isn't hot enough for it to be worth it. See
|
||||
// #91445 for details.
|
||||
inner.names.insert(string, name);
|
||||
name
|
||||
let (idx, is_new) = inner.strings.insert_full(string);
|
||||
debug_assert!(is_new); // due to the get_index_of check above
|
||||
|
||||
Symbol::new(idx as u32)
|
||||
}
|
||||
|
||||
/// Get the symbol as a string.
|
||||
///
|
||||
/// [`Symbol::as_str()`] should be used in preference to this function.
|
||||
fn get(&self, symbol: Symbol) -> &str {
|
||||
self.0.lock().strings[symbol.0.as_usize()]
|
||||
self.0.lock().strings.get_index(symbol.0.as_usize()).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::create_default_session_globals_then;
|
|||
|
||||
#[test]
|
||||
fn interner_tests() {
|
||||
let i = Interner::default();
|
||||
let i = Interner::prefill(&[]);
|
||||
// first one is zero:
|
||||
assert_eq!(i.intern("dog"), Symbol::new(0));
|
||||
// re-use gets the same entry:
|
||||
|
|
|
@ -119,25 +119,11 @@ impl NestedGoals<'_> {
|
|||
|
||||
#[derive(PartialEq, Eq, Debug, Hash, HashStable, Clone, Copy)]
|
||||
pub enum GenerateProofTree {
|
||||
Yes(UseGlobalCache),
|
||||
Yes,
|
||||
IfEnabled,
|
||||
Never,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Hash, HashStable, Clone, Copy)]
|
||||
pub enum UseGlobalCache {
|
||||
Yes,
|
||||
No,
|
||||
}
|
||||
impl UseGlobalCache {
|
||||
pub fn from_bool(use_cache: bool) -> Self {
|
||||
match use_cache {
|
||||
true => UseGlobalCache::Yes,
|
||||
false => UseGlobalCache::No,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait InferCtxtEvalExt<'tcx> {
|
||||
/// Evaluates a goal from **outside** of the trait solver.
|
||||
///
|
||||
|
|
|
@ -17,7 +17,7 @@ use rustc_middle::traits::solve::{Certainty, Goal};
|
|||
use rustc_middle::ty;
|
||||
|
||||
use crate::solve::inspect::ProofTreeBuilder;
|
||||
use crate::solve::{GenerateProofTree, InferCtxtEvalExt, UseGlobalCache};
|
||||
use crate::solve::{GenerateProofTree, InferCtxtEvalExt};
|
||||
|
||||
pub struct InspectGoal<'a, 'tcx> {
|
||||
infcx: &'a InferCtxt<'tcx>,
|
||||
|
@ -82,8 +82,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
|
|||
}
|
||||
|
||||
for &goal in &instantiated_goals {
|
||||
let (_, proof_tree) =
|
||||
infcx.evaluate_root_goal(goal, GenerateProofTree::Yes(UseGlobalCache::No));
|
||||
let (_, proof_tree) = infcx.evaluate_root_goal(goal, GenerateProofTree::Yes);
|
||||
let proof_tree = proof_tree.unwrap();
|
||||
visitor.visit_goal(&InspectGoal::new(
|
||||
infcx,
|
||||
|
@ -169,11 +168,11 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
|
|||
let mut candidates = vec![];
|
||||
let last_eval_step = match self.evaluation.evaluation.kind {
|
||||
inspect::CanonicalGoalEvaluationKind::Overflow
|
||||
| inspect::CanonicalGoalEvaluationKind::CacheHit(_) => {
|
||||
| inspect::CanonicalGoalEvaluationKind::CycleInStack => {
|
||||
warn!("unexpected root evaluation: {:?}", self.evaluation);
|
||||
return vec![];
|
||||
}
|
||||
inspect::CanonicalGoalEvaluationKind::Uncached { ref revisions } => {
|
||||
inspect::CanonicalGoalEvaluationKind::Evaluation { ref revisions } => {
|
||||
if let Some(last) = revisions.last() {
|
||||
last
|
||||
} else {
|
||||
|
@ -227,8 +226,7 @@ impl<'tcx> ProofTreeInferCtxtExt<'tcx> for InferCtxt<'tcx> {
|
|||
goal: Goal<'tcx, ty::Predicate<'tcx>>,
|
||||
visitor: &mut V,
|
||||
) -> ControlFlow<V::BreakTy> {
|
||||
let (_, proof_tree) =
|
||||
self.evaluate_root_goal(goal, GenerateProofTree::Yes(UseGlobalCache::No));
|
||||
let (_, proof_tree) = self.evaluate_root_goal(goal, GenerateProofTree::Yes);
|
||||
let proof_tree = proof_tree.unwrap();
|
||||
visitor.visit_goal(&InspectGoal::new(self, 0, &proof_tree))
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
//! This code is *a bit* of a mess and can hopefully be
|
||||
//! mostly ignored. For a general overview of how it works,
|
||||
//! see the comment on [ProofTreeBuilder].
|
||||
use std::mem;
|
||||
|
||||
use rustc_middle::traits::query::NoSolution;
|
||||
use rustc_middle::traits::solve::{
|
||||
CanonicalInput, Certainty, Goal, IsNormalizesToHack, QueryInput, QueryResult,
|
||||
|
@ -10,7 +12,6 @@ use rustc_middle::traits::solve::{
|
|||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_session::config::DumpSolverProofTree;
|
||||
|
||||
use crate::solve::eval_ctxt::UseGlobalCache;
|
||||
use crate::solve::{self, inspect, EvalCtxt, GenerateProofTree};
|
||||
|
||||
/// The core data structure when building proof trees.
|
||||
|
@ -34,12 +35,7 @@ use crate::solve::{self, inspect, EvalCtxt, GenerateProofTree};
|
|||
/// is called to recursively convert the whole structure to a
|
||||
/// finished proof tree.
|
||||
pub(in crate::solve) struct ProofTreeBuilder<'tcx> {
|
||||
state: Option<Box<BuilderData<'tcx>>>,
|
||||
}
|
||||
|
||||
struct BuilderData<'tcx> {
|
||||
tree: DebugSolver<'tcx>,
|
||||
use_global_cache: UseGlobalCache,
|
||||
state: Option<Box<DebugSolver<'tcx>>>,
|
||||
}
|
||||
|
||||
/// The current state of the proof tree builder, at most places
|
||||
|
@ -118,36 +114,46 @@ pub(in crate::solve) enum WipGoalEvaluationKind<'tcx> {
|
|||
Nested { is_normalizes_to_hack: IsNormalizesToHack },
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
pub(in crate::solve) enum WipCanonicalGoalEvaluationKind {
|
||||
#[derive(Eq, PartialEq)]
|
||||
pub(in crate::solve) enum WipCanonicalGoalEvaluationKind<'tcx> {
|
||||
Overflow,
|
||||
CacheHit(inspect::CacheHit),
|
||||
CycleInStack,
|
||||
Interned { revisions: &'tcx [inspect::GoalEvaluationStep<'tcx>] },
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for WipCanonicalGoalEvaluationKind<'_> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Overflow => write!(f, "Overflow"),
|
||||
Self::CycleInStack => write!(f, "CycleInStack"),
|
||||
Self::Interned { revisions: _ } => f.debug_struct("Interned").finish_non_exhaustive(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
struct WipCanonicalGoalEvaluation<'tcx> {
|
||||
goal: CanonicalInput<'tcx>,
|
||||
kind: Option<WipCanonicalGoalEvaluationKind>,
|
||||
kind: Option<WipCanonicalGoalEvaluationKind<'tcx>>,
|
||||
/// Only used for uncached goals. After we finished evaluating
|
||||
/// the goal, this is interned and moved into `kind`.
|
||||
revisions: Vec<WipGoalEvaluationStep<'tcx>>,
|
||||
result: Option<QueryResult<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'tcx> WipCanonicalGoalEvaluation<'tcx> {
|
||||
fn finalize(self) -> inspect::CanonicalGoalEvaluation<'tcx> {
|
||||
let kind = match self.kind {
|
||||
Some(WipCanonicalGoalEvaluationKind::Overflow) => {
|
||||
assert!(self.revisions.is_empty());
|
||||
let kind = match self.kind.unwrap() {
|
||||
WipCanonicalGoalEvaluationKind::Overflow => {
|
||||
inspect::CanonicalGoalEvaluationKind::Overflow
|
||||
}
|
||||
Some(WipCanonicalGoalEvaluationKind::CacheHit(hit)) => {
|
||||
inspect::CanonicalGoalEvaluationKind::CacheHit(hit)
|
||||
WipCanonicalGoalEvaluationKind::CycleInStack => {
|
||||
inspect::CanonicalGoalEvaluationKind::CycleInStack
|
||||
}
|
||||
WipCanonicalGoalEvaluationKind::Interned { revisions } => {
|
||||
inspect::CanonicalGoalEvaluationKind::Evaluation { revisions }
|
||||
}
|
||||
None => inspect::CanonicalGoalEvaluationKind::Uncached {
|
||||
revisions: self
|
||||
.revisions
|
||||
.into_iter()
|
||||
.map(WipGoalEvaluationStep::finalize)
|
||||
.collect(),
|
||||
},
|
||||
};
|
||||
|
||||
inspect::CanonicalGoalEvaluation { goal: self.goal, kind, result: self.result.unwrap() }
|
||||
|
@ -226,33 +232,20 @@ impl<'tcx> WipProbeStep<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> ProofTreeBuilder<'tcx> {
|
||||
fn new(
|
||||
state: impl Into<DebugSolver<'tcx>>,
|
||||
use_global_cache: UseGlobalCache,
|
||||
) -> ProofTreeBuilder<'tcx> {
|
||||
ProofTreeBuilder {
|
||||
state: Some(Box::new(BuilderData { tree: state.into(), use_global_cache })),
|
||||
}
|
||||
fn new(state: impl Into<DebugSolver<'tcx>>) -> ProofTreeBuilder<'tcx> {
|
||||
ProofTreeBuilder { state: Some(Box::new(state.into())) }
|
||||
}
|
||||
|
||||
fn nested<T: Into<DebugSolver<'tcx>>>(&self, state: impl FnOnce() -> T) -> Self {
|
||||
match &self.state {
|
||||
Some(prev_state) => Self {
|
||||
state: Some(Box::new(BuilderData {
|
||||
tree: state().into(),
|
||||
use_global_cache: prev_state.use_global_cache,
|
||||
})),
|
||||
},
|
||||
None => Self { state: None },
|
||||
}
|
||||
ProofTreeBuilder { state: self.state.as_ref().map(|_| Box::new(state().into())) }
|
||||
}
|
||||
|
||||
fn as_mut(&mut self) -> Option<&mut DebugSolver<'tcx>> {
|
||||
self.state.as_mut().map(|boxed| &mut boxed.tree)
|
||||
self.state.as_deref_mut()
|
||||
}
|
||||
|
||||
pub fn finalize(self) -> Option<inspect::GoalEvaluation<'tcx>> {
|
||||
match self.state?.tree {
|
||||
match *self.state? {
|
||||
DebugSolver::GoalEvaluation(wip_goal_evaluation) => {
|
||||
Some(wip_goal_evaluation.finalize())
|
||||
}
|
||||
|
@ -260,13 +253,6 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn use_global_cache(&self) -> bool {
|
||||
self.state
|
||||
.as_ref()
|
||||
.map(|state| matches!(state.use_global_cache, UseGlobalCache::Yes))
|
||||
.unwrap_or(true)
|
||||
}
|
||||
|
||||
pub fn new_maybe_root(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
generate_proof_tree: GenerateProofTree,
|
||||
|
@ -276,10 +262,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
|
|||
GenerateProofTree::IfEnabled => {
|
||||
let opts = &tcx.sess.opts.unstable_opts;
|
||||
match opts.dump_solver_proof_tree {
|
||||
DumpSolverProofTree::Always => {
|
||||
let use_cache = opts.dump_solver_proof_tree_use_cache.unwrap_or(true);
|
||||
ProofTreeBuilder::new_root(UseGlobalCache::from_bool(use_cache))
|
||||
}
|
||||
DumpSolverProofTree::Always => ProofTreeBuilder::new_root(),
|
||||
// `OnError` is handled by reevaluating goals in error
|
||||
// reporting with `GenerateProofTree::Yes`.
|
||||
DumpSolverProofTree::OnError | DumpSolverProofTree::Never => {
|
||||
|
@ -287,12 +270,12 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
GenerateProofTree::Yes(use_cache) => ProofTreeBuilder::new_root(use_cache),
|
||||
GenerateProofTree::Yes => ProofTreeBuilder::new_root(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_root(use_global_cache: UseGlobalCache) -> ProofTreeBuilder<'tcx> {
|
||||
ProofTreeBuilder::new(DebugSolver::Root, use_global_cache)
|
||||
pub fn new_root() -> ProofTreeBuilder<'tcx> {
|
||||
ProofTreeBuilder::new(DebugSolver::Root)
|
||||
}
|
||||
|
||||
pub fn new_noop() -> ProofTreeBuilder<'tcx> {
|
||||
|
@ -336,9 +319,27 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn finalize_evaluation(
|
||||
&mut self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
) -> Option<&'tcx [inspect::GoalEvaluationStep<'tcx>]> {
|
||||
self.as_mut().map(|this| match this {
|
||||
DebugSolver::CanonicalGoalEvaluation(evaluation) => {
|
||||
let revisions = mem::take(&mut evaluation.revisions)
|
||||
.into_iter()
|
||||
.map(WipGoalEvaluationStep::finalize);
|
||||
let revisions = &*tcx.arena.alloc_from_iter(revisions);
|
||||
let kind = WipCanonicalGoalEvaluationKind::Interned { revisions };
|
||||
assert_eq!(evaluation.kind.replace(kind), None);
|
||||
revisions
|
||||
}
|
||||
_ => unreachable!(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn canonical_goal_evaluation(&mut self, canonical_goal_evaluation: ProofTreeBuilder<'tcx>) {
|
||||
if let Some(this) = self.as_mut() {
|
||||
match (this, canonical_goal_evaluation.state.unwrap().tree) {
|
||||
match (this, *canonical_goal_evaluation.state.unwrap()) {
|
||||
(
|
||||
DebugSolver::GoalEvaluation(goal_evaluation),
|
||||
DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation),
|
||||
|
@ -348,7 +349,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn goal_evaluation_kind(&mut self, kind: WipCanonicalGoalEvaluationKind) {
|
||||
pub fn goal_evaluation_kind(&mut self, kind: WipCanonicalGoalEvaluationKind<'tcx>) {
|
||||
if let Some(this) = self.as_mut() {
|
||||
match this {
|
||||
DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => {
|
||||
|
@ -372,7 +373,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
|
|||
}
|
||||
pub fn goal_evaluation(&mut self, goal_evaluation: ProofTreeBuilder<'tcx>) {
|
||||
if let Some(this) = self.as_mut() {
|
||||
match (this, goal_evaluation.state.unwrap().tree) {
|
||||
match (this, *goal_evaluation.state.unwrap()) {
|
||||
(
|
||||
DebugSolver::AddedGoalsEvaluation(WipAddedGoalsEvaluation {
|
||||
evaluations, ..
|
||||
|
@ -396,7 +397,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
|
|||
}
|
||||
pub fn goal_evaluation_step(&mut self, goal_evaluation_step: ProofTreeBuilder<'tcx>) {
|
||||
if let Some(this) = self.as_mut() {
|
||||
match (this, goal_evaluation_step.state.unwrap().tree) {
|
||||
match (this, *goal_evaluation_step.state.unwrap()) {
|
||||
(
|
||||
DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluations),
|
||||
DebugSolver::GoalEvaluationStep(goal_evaluation_step),
|
||||
|
@ -444,7 +445,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
|
|||
|
||||
pub fn finish_probe(&mut self, probe: ProofTreeBuilder<'tcx>) {
|
||||
if let Some(this) = self.as_mut() {
|
||||
match (this, probe.state.unwrap().tree) {
|
||||
match (this, *probe.state.unwrap()) {
|
||||
(
|
||||
DebugSolver::Probe(WipProbe { steps, .. })
|
||||
| DebugSolver::GoalEvaluationStep(WipGoalEvaluationStep {
|
||||
|
@ -486,7 +487,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
|
|||
|
||||
pub fn added_goals_evaluation(&mut self, added_goals_evaluation: ProofTreeBuilder<'tcx>) {
|
||||
if let Some(this) = self.as_mut() {
|
||||
match (this, added_goals_evaluation.state.unwrap().tree) {
|
||||
match (this, *added_goals_evaluation.state.unwrap()) {
|
||||
(
|
||||
DebugSolver::GoalEvaluationStep(WipGoalEvaluationStep {
|
||||
evaluation: WipProbe { steps, .. },
|
||||
|
|
|
@ -38,9 +38,7 @@ mod project_goals;
|
|||
mod search_graph;
|
||||
mod trait_goals;
|
||||
|
||||
pub use eval_ctxt::{
|
||||
EvalCtxt, GenerateProofTree, InferCtxtEvalExt, InferCtxtSelectExt, UseGlobalCache,
|
||||
};
|
||||
pub use eval_ctxt::{EvalCtxt, GenerateProofTree, InferCtxtEvalExt, InferCtxtSelectExt};
|
||||
pub use fulfill::FulfillmentCtxt;
|
||||
pub(crate) use normalize::{deeply_normalize, deeply_normalize_with_skipped_universes};
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue