diff options
Diffstat (limited to 'compiler')
22 files changed, 296 insertions, 500 deletions
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index c9f5dd0f2c6..2fa602520dc 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -494,6 +494,11 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str .flatten(); features.extend(feats); + // FIXME: Move v8a to target definition list when earliest supported LLVM is 14. + if get_version() >= (14, 0, 0) && sess.target.arch == "aarch64" { + features.push("+v8a".into()); + } + if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) { sess.emit_err(TargetFeatureDisableOrEnable { features: f, diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 380fbd732d5..22f87514dd8 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -245,10 +245,8 @@ fn run_compiler( interface::run_compiler(config, |compiler| { let sopts = &compiler.session().opts; if sopts.describe_lints { - let mut lint_store = rustc_lint::new_lint_store( - sopts.unstable_opts.no_interleave_lints, - compiler.session().enable_internal_lints(), - ); + let mut lint_store = + rustc_lint::new_lint_store(compiler.session().enable_internal_lints()); let registered_lints = if let Some(register_lints) = compiler.register_lints() { register_lints(compiler.session(), &mut lint_store); diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs index ba58672e759..82a77416a19 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_method.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs @@ -173,13 +173,11 @@ fn compare_predicate_entailment<'tcx>( impl_to_placeholder_substs.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_substs); debug!("compare_impl_method: trait_to_placeholder_substs={:?}", trait_to_placeholder_substs); - let impl_m_generics = tcx.generics_of(impl_m.def_id); - let trait_m_generics = tcx.generics_of(trait_m.def_id); let impl_m_predicates = tcx.predicates_of(impl_m.def_id); let trait_m_predicates = tcx.predicates_of(trait_m.def_id); // Check region bounds. - check_region_bounds_on_impl_item(tcx, impl_m, trait_m, &trait_m_generics, &impl_m_generics)?; + check_region_bounds_on_impl_item(tcx, impl_m, trait_m, false)?; // Create obligations for each predicate declared by the impl // definition in the context of the trait's parameter @@ -338,6 +336,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>( // First, check a few of the same thing as `compare_impl_method`, just so we don't ICE during substitutions later. compare_number_of_generics(tcx, impl_m, trait_m, tcx.hir().span_if_local(impl_m.def_id), true)?; compare_generic_param_kinds(tcx, impl_m, trait_m, true)?; + check_region_bounds_on_impl_item(tcx, impl_m, trait_m, true)?; let trait_to_impl_substs = impl_trait_ref.substs; @@ -722,12 +721,14 @@ fn check_region_bounds_on_impl_item<'tcx>( tcx: TyCtxt<'tcx>, impl_m: &ty::AssocItem, trait_m: &ty::AssocItem, - trait_generics: &ty::Generics, - impl_generics: &ty::Generics, + delay: bool, ) -> Result<(), ErrorGuaranteed> { - let trait_params = trait_generics.own_counts().lifetimes; + let impl_generics = tcx.generics_of(impl_m.def_id); let impl_params = impl_generics.own_counts().lifetimes; + let trait_generics = tcx.generics_of(trait_m.def_id); + let trait_params = trait_generics.own_counts().lifetimes; + debug!( "check_region_bounds_on_impl_item: \ trait_generics={:?} \ @@ -761,12 +762,16 @@ fn check_region_bounds_on_impl_item<'tcx>( None }; - let reported = tcx.sess.emit_err(LifetimesOrBoundsMismatchOnTrait { - span, - item_kind: assoc_item_kind_str(impl_m), - ident: impl_m.ident(tcx), - generics_span, - }); + let reported = tcx + .sess + .create_err(LifetimesOrBoundsMismatchOnTrait { + span, + item_kind: assoc_item_kind_str(impl_m), + ident: impl_m.ident(tcx), + generics_span, + }) + .emit_unless(delay); + return Err(reported); } @@ -1504,18 +1509,10 @@ fn compare_type_predicate_entailment<'tcx>( let trait_to_impl_substs = impl_substs.rebase_onto(tcx, impl_ty.container_id(tcx), impl_trait_ref.substs); - let impl_ty_generics = tcx.generics_of(impl_ty.def_id); - let trait_ty_generics = tcx.generics_of(trait_ty.def_id); let impl_ty_predicates = tcx.predicates_of(impl_ty.def_id); let trait_ty_predicates = tcx.predicates_of(trait_ty.def_id); - check_region_bounds_on_impl_item( - tcx, - impl_ty, - trait_ty, - &trait_ty_generics, - &impl_ty_generics, - )?; + check_region_bounds_on_impl_item(tcx, impl_ty, trait_ty, false)?; let impl_ty_own_bounds = impl_ty_predicates.instantiate_own(tcx, impl_substs); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index ea141e815bf..1e9b5752130 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -22,7 +22,7 @@ use rustc_middle::ty::{self, Const, Ty, TyCtxt}; use rustc_session::Session; use rustc_span::symbol::Ident; use rustc_span::{self, Span}; -use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode}; +use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt}; use std::cell::{Cell, RefCell}; use std::ops::Deref; @@ -162,6 +162,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { infcx: &self.infcx, typeck_results: Some(self.typeck_results.borrow()), fallback_has_occurred: self.fallback_has_occurred.get(), + normalize_fn_sig: Box::new(|fn_sig| { + if fn_sig.has_escaping_bound_vars() { + return fn_sig; + } + self.probe(|_| { + let ocx = ObligationCtxt::new_in_snapshot(self); + let normalized_fn_sig = + ocx.normalize(&ObligationCause::dummy(), self.param_env, fn_sig); + if ocx.select_all_or_error().is_empty() { + let normalized_fn_sig = self.resolve_vars_if_possible(normalized_fn_sig); + if !normalized_fn_sig.needs_infer() { + return normalized_fn_sig; + } + } + fn_sig + }) + }), } } diff --git a/compiler/rustc_hir_typeck/src/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs index 869ad07c00d..b33e7b8d68c 100644 --- a/compiler/rustc_hir_typeck/src/inherited.rs +++ b/compiler/rustc_hir_typeck/src/inherited.rs @@ -1,7 +1,6 @@ use super::callee::DeferredCallResolution; use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::sync::Lrc; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::HirIdMap; @@ -11,9 +10,7 @@ use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::def_id::LocalDefIdMap; use rustc_span::{self, Span}; -use rustc_trait_selection::traits::{ - self, ObligationCause, ObligationCtxt, TraitEngine, TraitEngineExt as _, -}; +use rustc_trait_selection::traits::{self, TraitEngine, TraitEngineExt as _}; use std::cell::RefCell; use std::ops::Deref; @@ -92,29 +89,7 @@ impl<'tcx> Inherited<'tcx> { infcx: tcx .infer_ctxt() .ignoring_regions() - .with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)) - .with_normalize_fn_sig_for_diagnostic(Lrc::new(move |infcx, fn_sig| { - if fn_sig.has_escaping_bound_vars() { - return fn_sig; - } - infcx.probe(|_| { - let ocx = ObligationCtxt::new_in_snapshot(infcx); - let normalized_fn_sig = ocx.normalize( - &ObligationCause::dummy(), - // FIXME(compiler-errors): This is probably not the right param-env... - infcx.tcx.param_env(def_id), - fn_sig, - ); - if ocx.select_all_or_error().is_empty() { - let normalized_fn_sig = - infcx.resolve_vars_if_possible(normalized_fn_sig); - if !normalized_fn_sig.needs_infer() { - return normalized_fn_sig; - } - } - fn_sig - }) - })), + .with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)), def_id, typeck_results: RefCell::new(ty::TypeckResults::new(hir_owner)), } diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 2483ab724a4..4429e4f4362 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -77,10 +77,6 @@ impl<'tcx> InferCtxt<'tcx> { err_count_on_creation: self.err_count_on_creation, in_snapshot: self.in_snapshot.clone(), universe: self.universe.clone(), - normalize_fn_sig_for_diagnostic: self - .normalize_fn_sig_for_diagnostic - .as_ref() - .map(|f| f.clone()), intercrate: self.intercrate, } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index e2be8fb12d0..6bd1df97c16 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -95,6 +95,7 @@ pub mod nice_region_error; pub struct TypeErrCtxt<'a, 'tcx> { pub infcx: &'a InferCtxt<'tcx>, pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>, + pub normalize_fn_sig: Box<dyn Fn(ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx> + 'a>, pub fallback_has_occurred: bool, } @@ -1007,22 +1008,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } - fn normalize_fn_sig_for_diagnostic(&self, sig: ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx> { - if let Some(normalize) = &self.normalize_fn_sig_for_diagnostic { - normalize(self, sig) - } else { - sig - } - } - /// Given two `fn` signatures highlight only sub-parts that are different. fn cmp_fn_sig( &self, sig1: &ty::PolyFnSig<'tcx>, sig2: &ty::PolyFnSig<'tcx>, ) -> (DiagnosticStyledString, DiagnosticStyledString) { - let sig1 = &self.normalize_fn_sig_for_diagnostic(*sig1); - let sig2 = &self.normalize_fn_sig_for_diagnostic(*sig2); + let sig1 = &(self.normalize_fn_sig)(*sig1); + let sig2 = &(self.normalize_fn_sig)(*sig2); let get_lifetimes = |sig| { use rustc_hir::def::Namespace; diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 2bcb47cc383..2ce7cd8beba 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -80,7 +80,6 @@ pub struct InferOk<'tcx, T> { } pub type InferResult<'tcx, T> = Result<InferOk<'tcx, T>, TypeError<'tcx>>; -pub type Bound<T> = Option<T>; pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result" pub type FixupResult<'tcx, T> = Result<T, FixupError<'tcx>>; // "fixup result" @@ -334,9 +333,6 @@ pub struct InferCtxt<'tcx> { /// bound. universe: Cell<ty::UniverseIndex>, - normalize_fn_sig_for_diagnostic: - Option<Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>>, - /// During coherence we have to assume that other crates may add /// additional impls which we currently don't know about. /// @@ -573,8 +569,6 @@ pub struct InferCtxtBuilder<'tcx> { considering_regions: bool, /// Whether we are in coherence mode. intercrate: bool, - normalize_fn_sig_for_diagnostic: - Option<Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>>, } pub trait TyCtxtInferExt<'tcx> { @@ -587,7 +581,6 @@ impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> { tcx: self, defining_use_anchor: DefiningAnchor::Error, considering_regions: true, - normalize_fn_sig_for_diagnostic: None, intercrate: false, } } @@ -615,14 +608,6 @@ impl<'tcx> InferCtxtBuilder<'tcx> { self } - pub fn with_normalize_fn_sig_for_diagnostic( - mut self, - fun: Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>, - ) -> Self { - self.normalize_fn_sig_for_diagnostic = Some(fun); - self - } - /// Given a canonical value `C` as a starting point, create an /// inference context that contains each of the bound values /// within instantiated as a fresh variable. The `f` closure is @@ -644,13 +629,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { } pub fn build(&mut self) -> InferCtxt<'tcx> { - let InferCtxtBuilder { - tcx, - defining_use_anchor, - considering_regions, - ref normalize_fn_sig_for_diagnostic, - intercrate, - } = *self; + let InferCtxtBuilder { tcx, defining_use_anchor, considering_regions, intercrate } = *self; InferCtxt { tcx, defining_use_anchor, @@ -666,9 +645,6 @@ impl<'tcx> InferCtxtBuilder<'tcx> { in_snapshot: Cell::new(false), skip_leak_check: Cell::new(false), universe: Cell::new(ty::UniverseIndex::ROOT), - normalize_fn_sig_for_diagnostic: normalize_fn_sig_for_diagnostic - .as_ref() - .map(|f| f.clone()), intercrate, } } @@ -709,7 +685,12 @@ impl<'tcx> InferCtxt<'tcx> { /// Creates a `TypeErrCtxt` for emitting various inference errors. /// During typeck, use `FnCtxt::err_ctxt` instead. pub fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> { - TypeErrCtxt { infcx: self, typeck_results: None, fallback_has_occurred: false } + TypeErrCtxt { + infcx: self, + typeck_results: None, + fallback_has_occurred: false, + normalize_fn_sig: Box::new(|fn_sig| fn_sig), + } } pub fn is_in_snapshot(&self) -> bool { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 7f1d21bf1d8..6b5b5df9e2a 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -207,10 +207,7 @@ pub fn register_plugins<'a>( }); } - let mut lint_store = rustc_lint::new_lint_store( - sess.opts.unstable_opts.no_interleave_lints, - sess.enable_internal_lints(), - ); + let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints()); register_lints(sess, &mut lint_store); let registrars = diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index a03e7b0dae5..a6205f4d3a5 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -666,7 +666,6 @@ fn test_unstable_options_tracking_hash() { untracked!(mir_pretty_relative_line_numbers, true); untracked!(nll_facts, true); untracked!(no_analysis, true); - untracked!(no_interleave_lints, true); untracked!(no_leak_check, true); untracked!(no_parallel_llvm, true); untracked!(parse_only, true); diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index a7a4d0ca527..215df567e0e 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -25,8 +25,6 @@ use rustc_session::Session; use rustc_span::symbol::Ident; use rustc_span::Span; -use std::slice; - macro_rules! run_early_pass { ($cx:expr, $f:ident, $($args:expr),*) => ({ $cx.pass.$f(&$cx.context, $($args),*); }) } @@ -300,20 +298,14 @@ impl LintPass for EarlyLintPassObjects<'_> { } } -macro_rules! expand_early_lint_pass_impl_methods { - ([$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( - $(fn $name(&mut self, context: &EarlyContext<'_>, $($param: $arg),*) { - for obj in self.lints.iter_mut() { - obj.$name(context, $($param),*); - } - })* - ) -} - macro_rules! early_lint_pass_impl { - ([], [$($methods:tt)*]) => ( + ([], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( impl EarlyLintPass for EarlyLintPassObjects<'_> { - expand_early_lint_pass_impl_methods!([$($methods)*]); + $(fn $name(&mut self, context: &EarlyContext<'_>, $($param: $arg),*) { + for obj in self.lints.iter_mut() { + obj.$name(context, $($param),*); + } + })* } ) } @@ -371,87 +363,36 @@ impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [ast::Attribute], &'a [P<ast:: } } -fn early_lint_node<'a>( - sess: &Session, - warn_about_weird_lints: bool, - lint_store: &LintStore, - registered_tools: &RegisteredTools, - buffered: LintBuffer, - pass: impl EarlyLintPass, - check_node: impl EarlyCheckNode<'a>, -) -> LintBuffer { - let mut cx = EarlyContextAndPass { - context: EarlyContext::new( - sess, - warn_about_weird_lints, - lint_store, - registered_tools, - buffered, - ), - pass, - }; - - cx.with_lint_attrs(check_node.id(), check_node.attrs(), |cx| check_node.check(cx)); - cx.context.buffered -} - pub fn check_ast_node<'a>( sess: &Session, pre_expansion: bool, lint_store: &LintStore, registered_tools: &RegisteredTools, lint_buffer: Option<LintBuffer>, - builtin_lints: impl EarlyLintPass, + builtin_lints: impl EarlyLintPass + 'static, check_node: impl EarlyCheckNode<'a>, ) { let passes = if pre_expansion { &lint_store.pre_expansion_passes } else { &lint_store.early_passes }; let mut passes: Vec<_> = passes.iter().map(|p| (p)()).collect(); - let mut buffered = lint_buffer.unwrap_or_default(); - - if sess.opts.unstable_opts.no_interleave_lints { - for (i, pass) in passes.iter_mut().enumerate() { - buffered = - sess.prof.verbose_generic_activity_with_arg("run_lint", pass.name()).run(|| { - early_lint_node( - sess, - !pre_expansion && i == 0, - lint_store, - registered_tools, - buffered, - EarlyLintPassObjects { lints: slice::from_mut(pass) }, - check_node, - ) - }); - } - } else { - buffered = early_lint_node( + passes.push(Box::new(builtin_lints)); + + let mut cx = EarlyContextAndPass { + context: EarlyContext::new( sess, !pre_expansion, lint_store, registered_tools, - buffered, - builtin_lints, - check_node, - ); - - if !passes.is_empty() { - buffered = early_lint_node( - sess, - false, - lint_store, - registered_tools, - buffered, - EarlyLintPassObjects { lints: &mut passes[..] }, - check_node, - ); - } - } + lint_buffer.unwrap_or_default(), + ), + pass: EarlyLintPassObjects { lints: &mut passes[..] }, + }; + cx.with_lint_attrs(check_node.id(), check_node.attrs(), |cx| check_node.check(cx)); // All of the buffered lints should have been emitted at this point. // If not, that means that we somehow buffered a lint for a node id // that was not lint-checked (perhaps it doesn't exist?). This is a bug. - for (id, lints) in buffered.map { + for (id, lints) in cx.context.buffered.map { for early_lint in lints { sess.delay_span_bug( early_lint.span, diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 1d0b3f34d5d..e1aedc26d1b 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -28,7 +28,6 @@ use rustc_span::Span; use std::any::Any; use std::cell::Cell; -use std::slice; /// Extract the `LintStore` from the query context. /// This function exists because we've erased `LintStore` as `dyn Any` in the context. @@ -313,45 +312,42 @@ impl LintPass for LateLintPassObjects<'_, '_> { } } -macro_rules! expand_late_lint_pass_impl_methods { - ([$hir:tt], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( - $(fn $name(&mut self, context: &LateContext<$hir>, $($param: $arg),*) { - for obj in self.lints.iter_mut() { - obj.$name(context, $($param),*); - } - })* - ) -} - macro_rules! late_lint_pass_impl { - ([], [$hir:tt], $methods:tt) => { + ([], [$hir:tt], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => { impl<$hir> LateLintPass<$hir> for LateLintPassObjects<'_, $hir> { - expand_late_lint_pass_impl_methods!([$hir], $methods); + $(fn $name(&mut self, context: &LateContext<$hir>, $($param: $arg),*) { + for obj in self.lints.iter_mut() { + obj.$name(context, $($param),*); + } + })* } }; } crate::late_lint_methods!(late_lint_pass_impl, [], ['tcx]); -fn late_lint_mod_pass<'tcx, T: LateLintPass<'tcx>>( +pub(super) fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>( tcx: TyCtxt<'tcx>, module_def_id: LocalDefId, - pass: T, + builtin_lints: T, ) { - let effective_visibilities = &tcx.effective_visibilities(()); - let context = LateContext { tcx, enclosing_body: None, cached_typeck_results: Cell::new(None), param_env: ty::ParamEnv::empty(), - effective_visibilities, + effective_visibilities: &tcx.effective_visibilities(()), lint_store: unerased_lint_store(tcx), last_node_with_lint_attrs: tcx.hir().local_def_id_to_hir_id(module_def_id), generics: None, only_module: true, }; + let mut passes: Vec<_> = + unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)(tcx)).collect(); + passes.push(Box::new(builtin_lints)); + let pass = LateLintPassObjects { lints: &mut passes[..] }; + let mut cx = LateContextAndPass { context, pass }; let (module, _span, hir_id) = tcx.hir().get_module(module_def_id); @@ -365,46 +361,29 @@ fn late_lint_mod_pass<'tcx, T: LateLintPass<'tcx>>( } } -pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx>>( - tcx: TyCtxt<'tcx>, - module_def_id: LocalDefId, - builtin_lints: T, -) { - if tcx.sess.opts.unstable_opts.no_interleave_lints { - // These passes runs in late_lint_crate with -Z no_interleave_lints - return; - } - - late_lint_mod_pass(tcx, module_def_id, builtin_lints); - - let mut passes: Vec<_> = - unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)(tcx)).collect(); - - if !passes.is_empty() { - late_lint_mod_pass(tcx, module_def_id, LateLintPassObjects { lints: &mut passes[..] }); - } -} - -fn late_lint_pass_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, pass: T) { - let effective_visibilities = &tcx.effective_visibilities(()); - +fn late_lint_crate<'tcx, T: LateLintPass<'tcx> + 'tcx>(tcx: TyCtxt<'tcx>, builtin_lints: T) { let context = LateContext { tcx, enclosing_body: None, cached_typeck_results: Cell::new(None), param_env: ty::ParamEnv::empty(), - effective_visibilities, + effective_visibilities: &tcx.effective_visibilities(()), lint_store: unerased_lint_store(tcx), last_node_with_lint_attrs: hir::CRATE_HIR_ID, generics: None, only_module: false, }; + let mut passes = + unerased_lint_store(tcx).late_passes.iter().map(|p| (p)(tcx)).collect::<Vec<_>>(); + passes.push(Box::new(builtin_lints)); + let pass = LateLintPassObjects { lints: &mut passes[..] }; + let mut cx = LateContextAndPass { context, pass }; // Visit the whole crate. cx.with_lint_attrs(hir::CRATE_HIR_ID, |cx| { - // since the root module isn't visited as an item (because it isn't an + // Since the root module isn't visited as an item (because it isn't an // item), warn for it here. lint_callback!(cx, check_crate,); tcx.hir().walk_toplevel_module(cx); @@ -413,41 +392,8 @@ fn late_lint_pass_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, pass: T) }) } -fn late_lint_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, builtin_lints: T) { - let mut passes = - unerased_lint_store(tcx).late_passes.iter().map(|p| (p)(tcx)).collect::<Vec<_>>(); - - if !tcx.sess.opts.unstable_opts.no_interleave_lints { - if !passes.is_empty() { - late_lint_pass_crate(tcx, LateLintPassObjects { lints: &mut passes[..] }); - } - - late_lint_pass_crate(tcx, builtin_lints); - } else { - for pass in &mut passes { - tcx.sess.prof.verbose_generic_activity_with_arg("run_late_lint", pass.name()).run( - || { - late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) }); - }, - ); - } - - let mut passes: Vec<_> = - unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)(tcx)).collect(); - - for pass in &mut passes { - tcx.sess - .prof - .verbose_generic_activity_with_arg("run_late_module_lint", pass.name()) - .run(|| { - late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) }); - }); - } - } -} - /// Performs lint checking on a crate. -pub fn check_crate<'tcx, T: LateLintPass<'tcx>>( +pub fn check_crate<'tcx, T: LateLintPass<'tcx> + 'tcx>( tcx: TyCtxt<'tcx>, builtin_lints: impl FnOnce() -> T + Send, ) { diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index b6027476adf..10bae36e0fd 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -127,132 +127,116 @@ fn lint_mod(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { late::late_lint_mod(tcx, module_def_id, BuiltinCombinedModuleLateLintPass::new()); } -macro_rules! pre_expansion_lint_passes { - ($macro:path, $args:tt) => { - $macro!($args, [KeywordIdents: KeywordIdents,]); - }; -} - -macro_rules! early_lint_passes { - ($macro:path, $args:tt) => { - $macro!( - $args, - [ - UnusedParens: UnusedParens, - UnusedBraces: UnusedBraces, - UnusedImportBraces: UnusedImportBraces, - UnsafeCode: UnsafeCode, - SpecialModuleName: SpecialModuleName, - AnonymousParameters: AnonymousParameters, - EllipsisInclusiveRangePatterns: EllipsisInclusiveRangePatterns::default(), - NonCamelCaseTypes: NonCamelCaseTypes, - DeprecatedAttr: DeprecatedAttr::new(), - WhileTrue: WhileTrue, - NonAsciiIdents: NonAsciiIdents, - HiddenUnicodeCodepoints: HiddenUnicodeCodepoints, - IncompleteFeatures: IncompleteFeatures, - RedundantSemicolons: RedundantSemicolons, - UnusedDocComment: UnusedDocComment, - UnexpectedCfgs: UnexpectedCfgs, - ] - ); - }; -} - -macro_rules! declare_combined_early_pass { - ([$name:ident], $passes:tt) => ( - early_lint_methods!(declare_combined_early_lint_pass, [pub $name, $passes]); - ) -} - -pre_expansion_lint_passes!(declare_combined_early_pass, [BuiltinCombinedPreExpansionLintPass]); -early_lint_passes!(declare_combined_early_pass, [BuiltinCombinedEarlyLintPass]); - -macro_rules! late_lint_passes { - ($macro:path, $args:tt) => { - $macro!( - $args, - [ - // Tracks state across modules - UnnameableTestItems: UnnameableTestItems::new(), - // Tracks attributes of parents - MissingDoc: MissingDoc::new(), - // Builds a global list of all impls of `Debug`. - // FIXME: Turn the computation of types which implement Debug into a query - // and change this to a module lint pass - MissingDebugImplementations: MissingDebugImplementations::default(), - // Keeps a global list of foreign declarations. - ClashingExternDeclarations: ClashingExternDeclarations::new(), - ] - ); - }; -} - -macro_rules! late_lint_mod_passes { - ($macro:path, $args:tt) => { - $macro!( - $args, - [ - ForLoopsOverFallibles: ForLoopsOverFallibles, - DerefIntoDynSupertrait: DerefIntoDynSupertrait, - HardwiredLints: HardwiredLints, - ImproperCTypesDeclarations: ImproperCTypesDeclarations, - ImproperCTypesDefinitions: ImproperCTypesDefinitions, - VariantSizeDifferences: VariantSizeDifferences, - BoxPointers: BoxPointers, - PathStatements: PathStatements, - LetUnderscore: LetUnderscore, - // Depends on referenced function signatures in expressions - UnusedResults: UnusedResults, - NonUpperCaseGlobals: NonUpperCaseGlobals, - NonShorthandFieldPatterns: NonShorthandFieldPatterns, - UnusedAllocation: UnusedAllocation, - // Depends on types used in type definitions - MissingCopyImplementations: MissingCopyImplementations, - // Depends on referenced function signatures in expressions - MutableTransmutes: MutableTransmutes, - TypeAliasBounds: TypeAliasBounds, - TrivialConstraints: TrivialConstraints, - TypeLimits: TypeLimits::new(), - NonSnakeCase: NonSnakeCase, - InvalidNoMangleItems: InvalidNoMangleItems, - // Depends on effective visibilities - UnreachablePub: UnreachablePub, - ExplicitOutlivesRequirements: ExplicitOutlivesRequirements, - InvalidValue: InvalidValue, - DerefNullPtr: DerefNullPtr, - // May Depend on constants elsewhere - UnusedBrokenConst: UnusedBrokenConst, - UnstableFeatures: UnstableFeatures, - ArrayIntoIter: ArrayIntoIter::default(), - DropTraitConstraints: DropTraitConstraints, - TemporaryCStringAsPtr: TemporaryCStringAsPtr, - NonPanicFmt: NonPanicFmt, - NoopMethodCall: NoopMethodCall, - EnumIntrinsicsNonEnums: EnumIntrinsicsNonEnums, - InvalidAtomicOrdering: InvalidAtomicOrdering, - NamedAsmLabels: NamedAsmLabels, - OpaqueHiddenInferredBound: OpaqueHiddenInferredBound, - ] - ); - }; -} - -macro_rules! declare_combined_late_pass { - ([$v:vis $name:ident], $passes:tt) => ( - late_lint_methods!(declare_combined_late_lint_pass, [$v $name, $passes], ['tcx]); - ) -} +early_lint_methods!( + declare_combined_early_lint_pass, + [ + pub BuiltinCombinedPreExpansionLintPass, + [ + KeywordIdents: KeywordIdents, + ] + ] +); + +early_lint_methods!( + declare_combined_early_lint_pass, + [ + pub BuiltinCombinedEarlyLintPass, + [ + UnusedParens: UnusedParens, + UnusedBraces: UnusedBraces, + UnusedImportBraces: UnusedImportBraces, + UnsafeCode: UnsafeCode, + SpecialModuleName: SpecialModuleName, + AnonymousParameters: AnonymousParameters, + EllipsisInclusiveRangePatterns: EllipsisInclusiveRangePatterns::default(), + NonCamelCaseTypes: NonCamelCaseTypes, + DeprecatedAttr: DeprecatedAttr::new(), + WhileTrue: WhileTrue, + NonAsciiIdents: NonAsciiIdents, + HiddenUnicodeCodepoints: HiddenUnicodeCodepoints, + IncompleteFeatures: IncompleteFeatures, + RedundantSemicolons: RedundantSemicolons, + UnusedDocComment: UnusedDocComment, + UnexpectedCfgs: UnexpectedCfgs, + ] + ] +); // FIXME: Make a separate lint type which do not require typeck tables -late_lint_passes!(declare_combined_late_pass, [pub BuiltinCombinedLateLintPass]); - -late_lint_mod_passes!(declare_combined_late_pass, [BuiltinCombinedModuleLateLintPass]); - -pub fn new_lint_store(no_interleave_lints: bool, internal_lints: bool) -> LintStore { +late_lint_methods!( + declare_combined_late_lint_pass, + [ + pub BuiltinCombinedLateLintPass, + [ + // Tracks state across modules + UnnameableTestItems: UnnameableTestItems::new(), + // Tracks attributes of parents + MissingDoc: MissingDoc::new(), + // Builds a global list of all impls of `Debug`. + // FIXME: Turn the computation of types which implement Debug into a query + // and change this to a module lint pass + MissingDebugImplementations: MissingDebugImplementations::default(), + // Keeps a global list of foreign declarations. + ClashingExternDeclarations: ClashingExternDeclarations::new(), + ] + ], + ['tcx] +); + +late_lint_methods!( + declare_combined_late_lint_pass, + [ + BuiltinCombinedModuleLateLintPass, + [ + ForLoopsOverFallibles: ForLoopsOverFallibles, + DerefIntoDynSupertrait: DerefIntoDynSupertrait, + HardwiredLints: HardwiredLints, + ImproperCTypesDeclarations: ImproperCTypesDeclarations, + ImproperCTypesDefinitions: ImproperCTypesDefinitions, + VariantSizeDifferences: VariantSizeDifferences, + BoxPointers: BoxPointers, + PathStatements: PathStatements, + LetUnderscore: LetUnderscore, + // Depends on referenced function signatures in expressions + UnusedResults: UnusedResults, + NonUpperCaseGlobals: NonUpperCaseGlobals, + NonShorthandFieldPatterns: NonShorthandFieldPatterns, + UnusedAllocation: UnusedAllocation, + // Depends on types used in type definitions + MissingCopyImplementations: MissingCopyImplementations, + // Depends on referenced function signatures in expressions + MutableTransmutes: MutableTransmutes, + TypeAliasBounds: TypeAliasBounds, + TrivialConstraints: TrivialConstraints, + TypeLimits: TypeLimits::new(), + NonSnakeCase: NonSnakeCase, + InvalidNoMangleItems: InvalidNoMangleItems, + // Depends on effective visibilities + UnreachablePub: UnreachablePub, + ExplicitOutlivesRequirements: ExplicitOutlivesRequirements, + InvalidValue: InvalidValue, + DerefNullPtr: DerefNullPtr, + // May Depend on constants elsewhere + UnusedBrokenConst: UnusedBrokenConst, + UnstableFeatures: UnstableFeatures, + ArrayIntoIter: ArrayIntoIter::default(), + DropTraitConstraints: DropTraitConstraints, + TemporaryCStringAsPtr: TemporaryCStringAsPtr, + NonPanicFmt: NonPanicFmt, + NoopMethodCall: NoopMethodCall, + EnumIntrinsicsNonEnums: EnumIntrinsicsNonEnums, + InvalidAtomicOrdering: InvalidAtomicOrdering, + NamedAsmLabels: NamedAsmLabels, + OpaqueHiddenInferredBound: OpaqueHiddenInferredBound, + ] + ], + ['tcx] +); + +pub fn new_lint_store(internal_lints: bool) -> LintStore { let mut lint_store = LintStore::new(); - register_builtins(&mut lint_store, no_interleave_lints); + register_builtins(&mut lint_store); if internal_lints { register_internals(&mut lint_store); } @@ -263,54 +247,17 @@ pub fn new_lint_store(no_interleave_lints: bool, internal_lints: bool) -> LintSt /// Tell the `LintStore` about all the built-in lints (the ones /// defined in this crate and the ones defined in /// `rustc_session::lint::builtin`). -fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) { +fn register_builtins(store: &mut LintStore) { macro_rules! add_lint_group { ($name:expr, $($lint:ident),*) => ( store.register_group(false, $name, None, vec![$(LintId::of($lint)),*]); ) } - macro_rules! register_early_pass { - ($method:ident, $ty:ident, $constructor:expr) => { - store.register_lints(&$ty::get_lints()); - store.$method(|| Box::new($constructor)); - }; - } - - macro_rules! register_late_pass { - ($method:ident, $ty:ident, $constructor:expr) => { - store.register_lints(&$ty::get_lints()); - store.$method(|_| Box::new($constructor)); - }; - } - - macro_rules! register_early_passes { - ($method:ident, [$($passes:ident: $constructor:expr,)*]) => ( - $( - register_early_pass!($method, $passes, $constructor); - )* - ) - } - - macro_rules! register_late_passes { - ($method:ident, [$($passes:ident: $constructor:expr,)*]) => ( - $( - register_late_pass!($method, $passes, $constructor); - )* - ) - } - - if no_interleave_lints { - pre_expansion_lint_passes!(register_early_passes, register_pre_expansion_pass); - early_lint_passes!(register_early_passes, register_early_pass); - late_lint_passes!(register_late_passes, register_late_pass); - late_lint_mod_passes!(register_late_passes, register_late_mod_pass); - } else { - store.register_lints(&BuiltinCombinedPreExpansionLintPass::get_lints()); - store.register_lints(&BuiltinCombinedEarlyLintPass::get_lints()); - store.register_lints(&BuiltinCombinedModuleLateLintPass::get_lints()); - store.register_lints(&BuiltinCombinedLateLintPass::get_lints()); - } + store.register_lints(&BuiltinCombinedPreExpansionLintPass::get_lints()); + store.register_lints(&BuiltinCombinedEarlyLintPass::get_lints()); + store.register_lints(&BuiltinCombinedModuleLateLintPass::get_lints()); + store.register_lints(&BuiltinCombinedLateLintPass::get_lints()); add_lint_group!( "nonstandard_style", diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index fc11d092ccb..2f53986139e 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -1,7 +1,6 @@ use crate::context::{EarlyContext, LateContext}; use rustc_ast as ast; -use rustc_data_structures::sync; use rustc_hir as hir; use rustc_session::lint::builtin::HardwiredLints; use rustc_session::lint::LintPass; @@ -66,16 +65,10 @@ macro_rules! late_lint_methods { // FIXME: eliminate the duplication with `Visitor`. But this also // contains a few lint-specific methods with no equivalent in `Visitor`. -macro_rules! expand_lint_pass_methods { - ($context:ty, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( - $(#[inline(always)] fn $name(&mut self, _: $context, $(_: $arg),*) {})* - ) -} - macro_rules! declare_late_lint_pass { - ([], [$hir:tt], [$($methods:tt)*]) => ( + ([], [$hir:tt], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( pub trait LateLintPass<$hir>: LintPass { - expand_lint_pass_methods!(&LateContext<$hir>, [$($methods)*]); + $(#[inline(always)] fn $name(&mut self, _: &LateContext<$hir>, $(_: $arg),*) {})* } ) } @@ -175,16 +168,10 @@ macro_rules! early_lint_methods { ) } -macro_rules! expand_early_lint_pass_methods { - ($context:ty, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( - $(#[inline(always)] fn $name(&mut self, _: $context, $(_: $arg),*) {})* - ) -} - macro_rules! declare_early_lint_pass { - ([], [$($methods:tt)*]) => ( + ([], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( pub trait EarlyLintPass: LintPass { - expand_early_lint_pass_methods!(&EarlyContext<'_>, [$($methods)*]); + $(#[inline(always)] fn $name(&mut self, _: &EarlyContext<'_>, $(_: $arg),*) {})* } ) } @@ -243,5 +230,5 @@ macro_rules! declare_combined_early_lint_pass { } /// A lint pass boxed up as a trait object. -pub type EarlyLintPassObject = Box<dyn EarlyLintPass + sync::Send + 'static>; -pub type LateLintPassObject<'tcx> = Box<dyn LateLintPass<'tcx> + sync::Send + 'tcx>; +pub type EarlyLintPassObject = Box<dyn EarlyLintPass + 'static>; +pub type LateLintPassObject<'tcx> = Box<dyn LateLintPass<'tcx> + 'tcx>; diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index f4562cdfb88..70b98e59a8b 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -32,13 +32,23 @@ impl<'tcx> Value<TyCtxt<'tcx>> for ty::SymbolName<'_> { } impl<'tcx> Value<TyCtxt<'tcx>> for ty::Binder<'_, ty::FnSig<'_>> { - fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo]) -> Self { + fn from_cycle_error(tcx: TyCtxt<'tcx>, stack: &[QueryInfo]) -> Self { let err = tcx.ty_error(); - // FIXME(compiler-errors): It would be nice if we could get the - // query key, so we could at least generate a fn signature that - // has the right arity. + + let arity = if let Some(frame) = stack.get(0) + && frame.query.name == "fn_sig" + && let Some(def_id) = frame.query.def_id + && let Some(node) = tcx.hir().get_if_local(def_id) + && let Some(sig) = node.fn_sig() + { + sig.decl.inputs.len() + sig.decl.implicit_self.has_implicit_self() as usize + } else { + tcx.sess.abort_if_errors(); + unreachable!() + }; + let fn_sig = ty::Binder::dummy(tcx.mk_fn_sig( - [].into_iter(), + std::iter::repeat(err).take(arity), err, false, rustc_hir::Unsafety::Normal, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index f9ee202466f..01a9361e786 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1414,8 +1414,6 @@ options! { "run all passes except codegen; no output"), no_generate_arange_section: bool = (false, parse_no_flag, [TRACKED], "omit DWARF address ranges that give faster lookups"), - no_interleave_lints: bool = (false, parse_no_flag, [UNTRACKED], - "execute lints separately; allows benchmarking individual lints"), no_leak_check: bool = (false, parse_no_flag, [UNTRACKED], "disable the 'leak check' for subtyping; unsound, but useful for tests"), no_link: bool = (false, parse_no_flag, [TRACKED], diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 99724fb28db..899e30275a0 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -11,8 +11,8 @@ use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::util::impl_subject_and_oblig; use crate::traits::SkipLeakCheck; use crate::traits::{ - self, Normalized, Obligation, ObligationCause, ObligationCtxt, PredicateObligation, - PredicateObligations, SelectionContext, + self, Obligation, ObligationCause, ObligationCtxt, PredicateObligation, PredicateObligations, + SelectionContext, }; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::Diagnostic; @@ -30,6 +30,8 @@ use std::fmt::Debug; use std::iter; use std::ops::ControlFlow; +use super::NormalizeExt; + /// Whether we do the orphan check relative to this crate or /// to some remote crate. #[derive(Copy, Clone, Debug)] @@ -128,8 +130,8 @@ fn with_fresh_ty_vars<'cx, 'tcx>( predicates: tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs).predicates, }; - let Normalized { value: mut header, obligations } = - traits::normalize(selcx, param_env, ObligationCause::dummy(), header); + let InferOk { value: mut header, obligations } = + selcx.infcx.at(&ObligationCause::dummy(), param_env).normalize(header); header.predicates.extend(obligations.into_iter().map(|o| o.predicate)); header diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 64d01ddb09a..c028e89e4ea 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -112,6 +112,24 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { self.register_infer_ok_obligations(infer_ok) } + /// Makes `expected <: actual`. + pub fn eq_exp<T>( + &self, + cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + a_is_expected: bool, + a: T, + b: T, + ) -> Result<(), TypeError<'tcx>> + where + T: ToTrace<'tcx>, + { + self.infcx + .at(cause, param_env) + .eq_exp(a_is_expected, a, b) + .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) + } + pub fn eq<T: ToTrace<'tcx>>( &self, cause: &ObligationCause<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 049b24b3997..84e951e8023 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1577,32 +1577,26 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } self.probe(|_| { - let mut err = error.err; - let mut values = None; + let ocx = ObligationCtxt::new_in_snapshot(self); // try to find the mismatched types to report the error with. // // this can fail if the problem was higher-ranked, in which // cause I have no idea for a good error message. let bound_predicate = predicate.kind(); - if let ty::PredicateKind::Clause(ty::Clause::Projection(data)) = + let (values, err) = if let ty::PredicateKind::Clause(ty::Clause::Projection(data)) = bound_predicate.skip_binder() { - let mut selcx = SelectionContext::new(self); let data = self.replace_bound_vars_with_fresh_vars( obligation.cause.span, infer::LateBoundRegionConversionTime::HigherRankedType, bound_predicate.rebind(data), ); - let mut obligations = vec![]; - // FIXME(normalization): Change this to use `At::normalize` - let normalized_ty = super::normalize_projection_type( - &mut selcx, + let normalized_ty = ocx.normalize( + &obligation.cause, obligation.param_env, - data.projection_ty, - obligation.cause.clone(), - 0, - &mut obligations, + self.tcx + .mk_projection(data.projection_ty.item_def_id, data.projection_ty.substs), ); debug!(?obligation.cause, ?obligation.param_env); @@ -1618,19 +1612,34 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { | ObligationCauseCode::ObjectCastObligation(..) | ObligationCauseCode::OpaqueType ); - if let Err(new_err) = self.at(&obligation.cause, obligation.param_env).eq_exp( + let expected_ty = data.term.ty().unwrap(); + + // constrain inference variables a bit more to nested obligations from normalize so + // we can have more helpful errors. + ocx.select_where_possible(); + + if let Err(new_err) = ocx.eq_exp( + &obligation.cause, + obligation.param_env, is_normalized_ty_expected, normalized_ty, - data.term, + expected_ty, ) { - values = Some((data, is_normalized_ty_expected, normalized_ty, data.term)); - err = new_err; + (Some((data, is_normalized_ty_expected, normalized_ty, expected_ty)), new_err) + } else { + (None, error.err) } - } + } else { + (None, error.err) + }; let msg = values .and_then(|(predicate, _, normalized_ty, expected_ty)| { - self.maybe_detailed_projection_msg(predicate, normalized_ty, expected_ty) + self.maybe_detailed_projection_msg( + predicate, + normalized_ty.into(), + expected_ty.into(), + ) }) .unwrap_or_else(|| format!("type mismatch resolving `{}`", predicate)); let mut diag = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271, "{msg}"); @@ -1672,11 +1681,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { &mut diag, &obligation.cause, secondary_span, - values.map(|(_, is_normalized_ty_expected, normalized_ty, term)| { + values.map(|(_, is_normalized_ty_expected, normalized_ty, expected_ty)| { infer::ValuePairs::Terms(ExpectedFound::new( is_normalized_ty_expected, - normalized_ty, - term, + normalized_ty.into(), + expected_ty.into(), )) }), err, diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 371367f0deb..c6818a4e57d 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -56,7 +56,6 @@ pub use self::object_safety::astconv_object_safety_violations; pub use self::object_safety::is_vtable_safe_method; pub use self::object_safety::MethodViolationCode; pub use self::object_safety::ObjectSafetyViolation; -pub(crate) use self::project::{normalize, normalize_to}; pub use self::project::{normalize_projection_type, NormalizeExt}; pub use self::select::{EvaluationCache, SelectionCache, SelectionContext}; pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError}; diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 113803cd179..051660be9c4 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -50,6 +50,10 @@ pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::ProjectionTy<'tcx>> pub(super) struct InProgress; pub trait NormalizeExt<'tcx> { + /// Normalize a value using the `AssocTypeNormalizer`. + /// + /// This normalization should be used when the type contains inference variables or the + /// projection may be fallible. fn normalize<T: TypeFoldable<'tcx>>(&self, t: T) -> InferOk<'tcx, T>; } @@ -57,7 +61,7 @@ impl<'tcx> NormalizeExt<'tcx> for At<'_, 'tcx> { fn normalize<T: TypeFoldable<'tcx>>(&self, value: T) -> InferOk<'tcx, T> { let mut selcx = SelectionContext::new(self.infcx); let Normalized { value, obligations } = - normalize(&mut selcx, self.param_env, self.cause.clone(), value); + normalize_with_depth(&mut selcx, self.param_env, self.cause.clone(), 0, value); InferOk { value, obligations } } } @@ -303,37 +307,6 @@ fn project_and_unify_type<'cx, 'tcx>( } } -/// Normalizes any associated type projections in `value`, replacing -/// them with a fully resolved type where possible. The return value -/// combines the normalized result and any additional obligations that -/// were incurred as result. -pub(crate) fn normalize<'a, 'b, 'tcx, T>( - selcx: &'a mut SelectionContext<'b, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - cause: ObligationCause<'tcx>, - value: T, -) -> Normalized<'tcx, T> -where - T: TypeFoldable<'tcx>, -{ - let mut obligations = Vec::new(); - let value = normalize_to(selcx, param_env, cause, value, &mut obligations); - Normalized { value, obligations } -} - -pub(crate) fn normalize_to<'a, 'b, 'tcx, T>( - selcx: &'a mut SelectionContext<'b, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - cause: ObligationCause<'tcx>, - value: T, - obligations: &mut Vec<PredicateObligation<'tcx>>, -) -> T -where - T: TypeFoldable<'tcx>, -{ - normalize_with_depth_to(selcx, param_env, cause, 0, value, obligations) -} - /// As `normalize`, but with a custom depth. pub(crate) fn normalize_with_depth<'a, 'b, 'tcx, T>( selcx: &'a mut SelectionContext<'b, 'tcx>, @@ -2324,10 +2297,11 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>( }, )); - let ty = super::normalize_to( + let ty = normalize_with_depth_to( selcx, obligation.param_env, cause.clone(), + obligation.recursion_depth + 1, tcx.bound_trait_impl_trait_tys(impl_fn_def_id) .map_bound(|tys| { tys.map_or_else(|_| tcx.ty_error(), |tys| tys[&obligation.predicate.item_def_id]) diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 1aed6630870..f899321fc01 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -23,6 +23,13 @@ use super::NoSolution; pub use rustc_middle::traits::query::NormalizationResult; pub trait QueryNormalizeExt<'tcx> { + /// Normalize a value using the `QueryNormalizer`. + /// + /// This normalization should *only* be used when the projection does not + /// have possible ambiguity or may not be well-formed. + /// + /// After codegen, when lifetimes do not matter, it is preferable to instead + /// use [`TyCtxt::normalize_erasing_regions`], which wraps this procedure. fn query_normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution> where T: TypeFoldable<'tcx>; |
