diff options
Diffstat (limited to 'compiler')
38 files changed, 282 insertions, 175 deletions
diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index 5a1b1c799eb..fd94e7e9341 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -45,8 +45,6 @@ ast_lowering_closure_cannot_be_static = closures cannot be static ast_lowering_coroutine_too_many_parameters = too many parameters for a coroutine (expected 0 or 1 parameters) -ast_lowering_default_parameter_in_binder = default parameter is not allowed in this binder - ast_lowering_does_not_support_modifiers = the `{$class_name}` register class does not support template modifiers @@ -58,6 +56,9 @@ ast_lowering_functional_record_update_destructuring_assignment = functional record updates are not allowed in destructuring assignments .suggestion = consider removing the trailing pattern +ast_lowering_generic_param_default_in_binder = + defaults for generic parameters are not allowed in `for<...>` binders + ast_lowering_generic_type_with_parentheses = parenthesized type parameters may only be used with a `Fn` trait .label = only `Fn` traits may use parentheses diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 718a5b03cf2..710690d0d86 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -397,8 +397,8 @@ pub enum BadReturnTypeNotation { } #[derive(Diagnostic)] -#[diag(ast_lowering_default_parameter_in_binder)] -pub(crate) struct UnexpectedDefaultParameterInBinder { +#[diag(ast_lowering_generic_param_default_in_binder)] +pub(crate) struct GenericParamDefaultInBinder { #[primary_span] pub span: Span, } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 45357aca533..c618953461c 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1241,11 +1241,13 @@ impl<'hir> LoweringContext<'_, 'hir> { coroutine_kind: Option<CoroutineKind>, ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) { let header = self.lower_fn_header(sig.header); + // Don't pass along the user-provided constness of trait associated functions; we don't want to + // synthesize a host effect param for them. We reject `const` on them during AST validation. + let constness = if kind == FnDeclKind::Inherent { sig.header.constness } else { Const::No }; let itctx = ImplTraitContext::Universal; - let (generics, decl) = - self.lower_generics(generics, sig.header.constness, id, &itctx, |this| { - this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind) - }); + let (generics, decl) = self.lower_generics(generics, constness, id, &itctx, |this| { + this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind) + }); (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) }) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 92fd29c47af..c7c77bf56b7 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -66,7 +66,6 @@ use rustc_session::parse::{add_feature_diagnostics, feature_err}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{DesugaringKind, Span, DUMMY_SP}; use smallvec::SmallVec; -use std::borrow::Cow; use std::collections::hash_map::Entry; use thin_vec::ThinVec; @@ -884,27 +883,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { binder: NodeId, generic_params: &[GenericParam], ) -> &'hir [hir::GenericParam<'hir>] { - let mut generic_params: Vec<_> = generic_params - .iter() - .map(|param| { - let param = match param.kind { - GenericParamKind::Type { ref default } if let Some(ty) = default => { - // Default type is not permitted in non-lifetime binders. - // So we emit an error and default to `None` to prevent - // potential ice. - self.dcx().emit_err(errors::UnexpectedDefaultParameterInBinder { - span: ty.span(), - }); - let param = GenericParam { - kind: GenericParamKind::Type { default: None }, - ..param.clone() - }; - Cow::Owned(param) - } - _ => Cow::Borrowed(param), - }; - self.lower_generic_param(param.as_ref(), hir::GenericParamSource::Binder) - }) + let mut generic_params: Vec<_> = self + .lower_generic_params_mut(generic_params, hir::GenericParamSource::Binder) .collect(); let extra_lifetimes = self.resolver.take_extra_lifetime_params(binder); debug!(?extra_lifetimes); @@ -2136,7 +2116,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { param: &GenericParam, source: hir::GenericParamSource, ) -> hir::GenericParam<'hir> { - let (name, kind) = self.lower_generic_param_kind(param); + let (name, kind) = self.lower_generic_param_kind(param, source); let hir_id = self.lower_node_id(param.id); self.lower_attrs(hir_id, ¶m.attrs); @@ -2155,6 +2135,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_generic_param_kind( &mut self, param: &GenericParam, + source: hir::GenericParamSource, ) -> (hir::ParamName, hir::GenericParamKind<'hir>) { match ¶m.kind { GenericParamKind::Lifetime => { @@ -2173,22 +2154,51 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { (param_name, kind) } GenericParamKind::Type { default, .. } => { - let kind = hir::GenericParamKind::Type { - default: default.as_ref().map(|x| { + // Not only do we deny type param defaults in binders but we also map them to `None` + // since later compiler stages cannot handle them (and shouldn't need to be able to). + let default = default + .as_ref() + .filter(|_| match source { + hir::GenericParamSource::Generics => true, + hir::GenericParamSource::Binder => { + self.dcx().emit_err(errors::GenericParamDefaultInBinder { + span: param.span(), + }); + + false + } + }) + .map(|def| { self.lower_ty( - x, + def, &ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault), ) - }), - synthetic: false, - }; + }); + + let kind = hir::GenericParamKind::Type { default, synthetic: false }; (hir::ParamName::Plain(self.lower_ident(param.ident)), kind) } GenericParamKind::Const { ty, kw_span: _, default } => { let ty = self .lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault)); - let default = default.as_ref().map(|def| self.lower_anon_const(def)); + + // Not only do we deny const param defaults in binders but we also map them to `None` + // since later compiler stages cannot handle them (and shouldn't need to be able to). + let default = default + .as_ref() + .filter(|_| match source { + hir::GenericParamSource::Generics => true, + hir::GenericParamSource::Binder => { + self.dcx().emit_err(errors::GenericParamDefaultInBinder { + span: param.span(), + }); + + false + } + }) + .map(|def| self.lower_anon_const(def)); + ( hir::ParamName::Plain(self.lower_ident(param.ident)), hir::GenericParamKind::Const { ty, default, is_host_effect: false }, diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index b5612c1820d..feea02c679c 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -233,8 +233,21 @@ ast_passes_tilde_const_disallowed = `~const` is not allowed here .item = this item cannot have `~const` trait bounds ast_passes_trait_fn_const = - functions in traits cannot be declared const - .label = functions in traits cannot be const + functions in {$in_impl -> + [true] trait impls + *[false] traits + } cannot be declared const + .label = functions in {$in_impl -> + [true] trait impls + *[false] traits + } cannot be const + .const_context_label = this declares all associated functions implicitly const + .remove_const_sugg = remove the `const`{$requires_multiple_changes -> + [true] {" ..."} + *[false] {""} + } + .make_impl_const_sugg = ... and declare the impl to be const instead + .make_trait_const_sugg = ... and declare the trait to be a `#[const_trait]` instead ast_passes_trait_object_single_bound = only a single explicit lifetime bound is permitted diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index bc5cf463f12..b69d4cccaf0 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -46,6 +46,21 @@ enum DisallowTildeConstContext<'a> { Item, } +enum TraitOrTraitImpl<'a> { + Trait { span: Span, constness: Option<Span> }, + TraitImpl { constness: Const, polarity: ImplPolarity, trait_ref: &'a TraitRef }, +} + +impl<'a> TraitOrTraitImpl<'a> { + fn constness(&self) -> Option<Span> { + match self { + Self::Trait { constness: Some(span), .. } + | Self::TraitImpl { constness: Const::Yes(span), .. } => Some(*span), + _ => None, + } + } +} + struct AstValidator<'a> { session: &'a Session, features: &'a Features, @@ -53,11 +68,7 @@ struct AstValidator<'a> { /// The span of the `extern` in an `extern { ... }` block, if any. extern_mod: Option<&'a Item>, - /// Are we inside a trait impl? - in_trait_impl: bool, - - /// Are we inside a const trait defn or impl? - in_const_trait_or_impl: bool, + outer_trait_or_trait_impl: Option<TraitOrTraitImpl<'a>>, has_proc_macro_decls: bool, @@ -78,24 +89,28 @@ struct AstValidator<'a> { impl<'a> AstValidator<'a> { fn with_in_trait_impl( &mut self, - is_in: bool, - constness: Option<Const>, + trait_: Option<(Const, ImplPolarity, &'a TraitRef)>, f: impl FnOnce(&mut Self), ) { - let old = mem::replace(&mut self.in_trait_impl, is_in); - let old_const = mem::replace( - &mut self.in_const_trait_or_impl, - matches!(constness, Some(Const::Yes(_))), + let old = mem::replace( + &mut self.outer_trait_or_trait_impl, + trait_.map(|(constness, polarity, trait_ref)| TraitOrTraitImpl::TraitImpl { + constness, + polarity, + trait_ref, + }), ); f(self); - self.in_trait_impl = old; - self.in_const_trait_or_impl = old_const; + self.outer_trait_or_trait_impl = old; } - fn with_in_trait(&mut self, is_const: bool, f: impl FnOnce(&mut Self)) { - let old = mem::replace(&mut self.in_const_trait_or_impl, is_const); + fn with_in_trait(&mut self, span: Span, constness: Option<Span>, f: impl FnOnce(&mut Self)) { + let old = mem::replace( + &mut self.outer_trait_or_trait_impl, + Some(TraitOrTraitImpl::Trait { span, constness }), + ); f(self); - self.in_const_trait_or_impl = old; + self.outer_trait_or_trait_impl = old; } fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) { @@ -291,10 +306,48 @@ impl<'a> AstValidator<'a> { } } - fn check_trait_fn_not_const(&self, constness: Const) { - if let Const::Yes(span) = constness { - self.dcx().emit_err(errors::TraitFnConst { span }); - } + fn check_trait_fn_not_const(&self, constness: Const, parent: &TraitOrTraitImpl<'a>) { + let Const::Yes(span) = constness else { + return; + }; + + let make_impl_const_sugg = if self.features.const_trait_impl + && let TraitOrTraitImpl::TraitImpl { + constness: Const::No, + polarity: ImplPolarity::Positive, + trait_ref, + } = parent + { + Some(trait_ref.path.span.shrink_to_lo()) + } else { + None + }; + + let make_trait_const_sugg = if self.features.const_trait_impl + && let TraitOrTraitImpl::Trait { span, constness: None } = parent + { + Some(span.shrink_to_lo()) + } else { + None + }; + + let parent_constness = parent.constness(); + self.dcx().emit_err(errors::TraitFnConst { + span, + in_impl: matches!(parent, TraitOrTraitImpl::TraitImpl { .. }), + const_context_label: parent_constness, + remove_const_sugg: ( + self.session.source_map().span_extend_while(span, |c| c == ' ').unwrap_or(span), + match parent_constness { + Some(_) => rustc_errors::Applicability::MachineApplicable, + None => rustc_errors::Applicability::MaybeIncorrect, + }, + ), + requires_multiple_changes: make_impl_const_sugg.is_some() + || make_trait_const_sugg.is_some(), + make_impl_const_sugg, + make_trait_const_sugg, + }); } fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) { @@ -817,7 +870,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self_ty, items, }) => { - self.with_in_trait_impl(true, Some(*constness), |this| { + self.with_in_trait_impl(Some((*constness, *polarity, t)), |this| { this.visibility_not_permitted( &item.vis, errors::VisibilityNotPermittedNote::TraitImpl, @@ -963,8 +1016,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } ItemKind::Trait(box Trait { is_auto, generics, bounds, items, .. }) => { - let is_const_trait = attr::contains_name(&item.attrs, sym::const_trait); - self.with_in_trait(is_const_trait, |this| { + let is_const_trait = + attr::find_by_name(&item.attrs, sym::const_trait).map(|attr| attr.span); + self.with_in_trait(item.span, is_const_trait, |this| { if *is_auto == IsAuto::Yes { // Auto traits cannot have generics, super traits nor contain items. this.deny_generic_params(generics, item.ident.span); @@ -977,8 +1031,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { // context for the supertraits. this.visit_vis(&item.vis); this.visit_ident(item.ident); - let disallowed = - (!is_const_trait).then(|| DisallowTildeConstContext::Trait(item.span)); + let disallowed = is_const_trait + .is_none() + .then(|| DisallowTildeConstContext::Trait(item.span)); this.with_tilde_const(disallowed, |this| { this.visit_generics(generics); walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits) @@ -1342,7 +1397,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> { let tilde_const_allowed = matches!(fk.header(), Some(FnHeader { constness: ast::Const::Yes(_), .. })) - || matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)) if self.in_const_trait_or_impl); + || matches!(fk.ctxt(), Some(FnCtxt::Assoc(_))) + && self + .outer_trait_or_trait_impl + .as_ref() + .and_then(TraitOrTraitImpl::constness) + .is_some(); let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk)); self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk)); @@ -1353,7 +1413,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_nomangle_item_asciionly(item.ident, item.span); } - if ctxt == AssocCtxt::Trait || !self.in_trait_impl { + if ctxt == AssocCtxt::Trait || self.outer_trait_or_trait_impl.is_none() { self.check_defaultness(item.span, item.kind.defaultness()); } @@ -1401,10 +1461,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { ); } - if ctxt == AssocCtxt::Trait || self.in_trait_impl { + if let Some(parent) = &self.outer_trait_or_trait_impl { self.visibility_not_permitted(&item.vis, errors::VisibilityNotPermittedNote::TraitImpl); if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind { - self.check_trait_fn_not_const(sig.header.constness); + self.check_trait_fn_not_const(sig.header.constness, parent); } } @@ -1414,7 +1474,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> { match &item.kind { AssocItemKind::Fn(box Fn { sig, generics, body, .. }) - if self.in_const_trait_or_impl + if self + .outer_trait_or_trait_impl + .as_ref() + .and_then(TraitOrTraitImpl::constness) + .is_some() || ctxt == AssocCtxt::Trait || matches!(sig.header.constness, Const::Yes(_)) => { @@ -1430,8 +1494,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { ); self.visit_fn(kind, item.span, item.id); } - _ => self - .with_in_trait_impl(false, None, |this| visit::walk_assoc_item(this, item, ctxt)), + _ => self.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt)), } } } @@ -1547,8 +1610,7 @@ pub fn check_crate( session, features, extern_mod: None, - in_trait_impl: false, - in_const_trait_or_impl: false, + outer_trait_or_trait_impl: None, has_proc_macro_decls: false, outer_impl_trait: None, disallow_tilde_const: Some(DisallowTildeConstContext::Item), diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 0cec4374be2..42ada39f515 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -1,7 +1,7 @@ //! Errors emitted by ast_passes. use rustc_ast::ParamKindOrd; -use rustc_errors::AddToDiagnostic; +use rustc_errors::{AddToDiagnostic, Applicability}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -49,6 +49,24 @@ pub struct TraitFnConst { #[primary_span] #[label] pub span: Span, + pub in_impl: bool, + #[label(ast_passes_const_context_label)] + pub const_context_label: Option<Span>, + #[suggestion(ast_passes_remove_const_sugg, code = "")] + pub remove_const_sugg: (Span, Applicability), + pub requires_multiple_changes: bool, + #[suggestion( + ast_passes_make_impl_const_sugg, + code = "const ", + applicability = "maybe-incorrect" + )] + pub make_impl_const_sugg: Option<Span>, + #[suggestion( + ast_passes_make_trait_const_sugg, + code = "#[const_trait]\n", + applicability = "maybe-incorrect" + )] + pub make_trait_const_sugg: Option<Span>, } #[derive(Diagnostic)] diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 3ec07572d1d..d824260f47c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -3067,7 +3067,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) -> Option<AnnotatedBorrowFnSignature<'tcx>> { // Define a fallback for when we can't match a closure. let fallback = || { - let is_closure = self.infcx.tcx.is_closure(self.mir_def_id().to_def_id()); + let is_closure = self.infcx.tcx.is_closure_or_coroutine(self.mir_def_id().to_def_id()); if is_closure { None } else { @@ -3277,7 +3277,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { sig: ty::PolyFnSig<'tcx>, ) -> Option<AnnotatedBorrowFnSignature<'tcx>> { debug!("annotate_fn_sig: did={:?} sig={:?}", did, sig); - let is_closure = self.infcx.tcx.is_closure(did.to_def_id()); + let is_closure = self.infcx.tcx.is_closure_or_coroutine(did.to_def_id()); let fn_hir_id = self.infcx.tcx.local_def_id_to_hir_id(did); let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(fn_hir_id)?; diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index f717d91c35c..5bd7cc9514c 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -22,7 +22,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { #[instrument(skip(self, body), level = "debug")] pub(super) fn check_signature_annotation(&mut self, body: &Body<'tcx>) { let mir_def_id = body.source.def_id().expect_local(); - if !self.tcx().is_closure(mir_def_id.to_def_id()) { + if !self.tcx().is_closure_or_coroutine(mir_def_id.to_def_id()) { return; } let user_provided_poly_sig = self.tcx().closure_user_provided_sig(mir_def_id); diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 3cc33b83434..b3fa7b7cd44 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -481,7 +481,7 @@ pub fn from_fn_attrs<'ll, 'tcx>( // `+multivalue` feature because the purpose of the wasm abi is to match // the WebAssembly specification, which has this feature. This won't be // needed when LLVM enables this `multivalue` feature by default. - if !cx.tcx.is_closure(instance.def_id()) { + if !cx.tcx.is_closure_or_coroutine(instance.def_id()) { let abi = cx.tcx.fn_sig(instance.def_id()).skip_binder().abi(); if abi == Abi::Wasm { function_features.push("+multivalue".to_string()); diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 33bfde03a31..51df14df644 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -58,11 +58,6 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) { return; } - // The entries of the map are only used to get a list of all files with - // coverage info. In the end the list of files is passed into - // `GlobalFileTable::new()` which internally do `.sort_unstable_by()`, so - // the iteration order here does not matter. - #[allow(rustc::potential_query_instability)] let function_coverage_entries = function_coverage_map .into_iter() .map(|(instance, function_coverage)| (instance, function_coverage.into_finished())) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 0befbb5a39b..733a77d24c2 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -10,7 +10,7 @@ use rustc_codegen_ssa::traits::{ BaseTypeMethods, BuilderMethods, ConstMethods, CoverageInfoBuilderMethods, MiscMethods, StaticMethods, }; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_llvm::RustString; use rustc_middle::bug; use rustc_middle::mir::coverage::CoverageKind; @@ -30,7 +30,7 @@ const VAR_ALIGN_BYTES: usize = 8; pub struct CrateCoverageContext<'ll, 'tcx> { /// Coverage data for each instrumented function identified by DefId. pub(crate) function_coverage_map: - RefCell<FxHashMap<Instance<'tcx>, FunctionCoverageCollector<'tcx>>>, + RefCell<FxIndexMap<Instance<'tcx>, FunctionCoverageCollector<'tcx>>>, pub(crate) pgo_func_name_var_map: RefCell<FxHashMap<Instance<'tcx>, &'ll llvm::Value>>, } @@ -44,8 +44,8 @@ impl<'ll, 'tcx> CrateCoverageContext<'ll, 'tcx> { pub fn take_function_coverage_map( &self, - ) -> FxHashMap<Instance<'tcx>, FunctionCoverageCollector<'tcx>> { - self.function_coverage_map.replace(FxHashMap::default()) + ) -> FxIndexMap<Instance<'tcx>, FunctionCoverageCollector<'tcx>> { + self.function_coverage_map.replace(FxIndexMap::default()) } } diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index f5f2416abb6..63fd7b42f7b 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -232,7 +232,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL, sym::track_caller => { - let is_closure = tcx.is_closure(did.to_def_id()); + let is_closure = tcx.is_closure_or_coroutine(did.to_def_id()); if !is_closure && let Some(fn_sig) = fn_sig() @@ -277,7 +277,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } } sym::target_feature => { - if !tcx.is_closure(did.to_def_id()) + if !tcx.is_closure_or_coroutine(did.to_def_id()) && let Some(fn_sig) = fn_sig() && fn_sig.skip_binder().unsafety() == hir::Unsafety::Normal { @@ -531,7 +531,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { // would result in this closure being compiled without the inherited target features, but this // is probably a poor usage of `#[inline(always)]` and easily avoided by not using the attribute. if tcx.features().target_feature_11 - && tcx.is_closure(did.to_def_id()) + && tcx.is_closure_or_coroutine(did.to_def_id()) && codegen_fn_attrs.inline != InlineAttr::Always { let owner_id = tcx.parent(did.to_def_id()); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs index fbc95072802..98276ff2e68 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs @@ -72,7 +72,7 @@ impl<'mir, 'tcx> ConstCx<'mir, 'tcx> { pub fn fn_sig(&self) -> PolyFnSig<'tcx> { let did = self.def_id().to_def_id(); - if self.tcx.is_closure(did) { + if self.tcx.is_closure_or_coroutine(did) { let ty = self.tcx.type_of(did).instantiate_identity(); let ty::Closure(_, args) = ty.kind() else { bug!("type_of closure not ty::Closure") }; args.as_closure().sig() diff --git a/compiler/rustc_error_codes/src/error_codes/E0379.md b/compiler/rustc_error_codes/src/error_codes/E0379.md index ab438e41447..35f546cfdb7 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0379.md +++ b/compiler/rustc_error_codes/src/error_codes/E0379.md @@ -6,6 +6,10 @@ Erroneous code example: trait Foo { const fn bar() -> u32; // error! } + +impl Foo for () { + const fn bar() -> u32 { 0 } // error! +} ``` Trait methods cannot be declared `const` by design. For more information, see diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 763bd4fc391..e6faad74384 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -525,7 +525,7 @@ declare_features! ( /// Allows the `#[must_not_suspend]` attribute. (unstable, must_not_suspend, "1.57.0", Some(83310)), /// Allows using `#[naked]` on functions. - (unstable, naked_functions, "1.9.0", Some(32408)), + (unstable, naked_functions, "1.9.0", Some(90957)), /// Allows specifying the as-needed link modifier (unstable, native_link_modifiers_as_needed, "1.53.0", Some(81490)), /// Allow negative trait implementations. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index b76edd554f8..2c34fc13919 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2110,12 +2110,6 @@ pub enum YieldSource { Yield, } -impl YieldSource { - pub fn is_await(&self) -> bool { - matches!(self, YieldSource::Await { .. }) - } -} - impl fmt::Display for YieldSource { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(match self { diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 5abc752309a..b44b2eefabb 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -315,7 +315,10 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { if is_host_effect { if let Some(idx) = host_effect_index { - bug!("parent also has host effect param? index: {idx}, def: {def_id:?}"); + tcx.dcx().span_delayed_bug( + param.span, + format!("parent also has host effect param? index: {idx}, def: {def_id:?}"), + ); } host_effect_index = Some(index as usize); diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 0ca0f7d2daf..2a408ac255c 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -125,7 +125,8 @@ pub(super) fn check_fn<'a, 'tcx>( // ty_span == binding_span iff this is a closure parameter with no type ascription, // or if it's an implicit `self` parameter traits::SizedArgumentType( - if ty_span == Some(param.span) && tcx.is_closure(fn_def_id.into()) { + if ty_span == Some(param.span) && tcx.is_closure_or_coroutine(fn_def_id.into()) + { None } else { ty_span diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 7d753216534..7425d6f8901 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -349,7 +349,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ExprKind::Index(base, idx, brackets_span) => { self.check_expr_index(base, idx, expr, brackets_span) } - ExprKind::Yield(value, ref src) => self.check_expr_yield(value, expr, src), + ExprKind::Yield(value, _) => self.check_expr_yield(value, expr), hir::ExprKind::Err(guar) => Ty::new_error(tcx, guar), } } @@ -3162,7 +3162,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, value: &'tcx hir::Expr<'tcx>, expr: &'tcx hir::Expr<'tcx>, - src: &'tcx hir::YieldSource, ) -> Ty<'tcx> { match self.resume_yield_tys { Some((resume_ty, yield_ty)) => { @@ -3170,14 +3169,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { resume_ty } - // Given that this `yield` expression was generated as a result of lowering a `.await`, - // we know that the yield type must be `()`; however, the context won't contain this - // information. Hence, we check the source of the yield expression here and check its - // value's type against `()` (this check should always hold). - None if src.is_await() => { - self.check_expr_coercible_to_type(value, Ty::new_unit(self.tcx), None); - Ty::new_unit(self.tcx) - } _ => { self.dcx().emit_err(YieldExprOutsideOfCoroutine { span: expr.span }); // Avoid expressions without types during writeback (#78653). diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs index 0cca779b156..e169b45d725 100644 --- a/compiler/rustc_hir_typeck/src/gather_locals.rs +++ b/compiler/rustc_hir_typeck/src/gather_locals.rs @@ -150,7 +150,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { // ascription, or if it's an implicit `self` parameter traits::SizedArgumentType( if ty_span == ident.span - && self.fcx.tcx.is_closure(self.fcx.body_id.into()) + && self.fcx.tcx.is_closure_or_coroutine(self.fcx.body_id.into()) { None } else { diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs index e68195acee0..b459f82f23e 100644 --- a/compiler/rustc_incremental/src/persist/file_format.rs +++ b/compiler/rustc_incremental/src/persist/file_format.rs @@ -55,18 +55,12 @@ where debug!("save: remove old file"); } Err(err) if err.kind() == io::ErrorKind::NotFound => (), - Err(err) => { - sess.dcx().emit_err(errors::DeleteOld { name, path: path_buf, err }); - return; - } + Err(err) => sess.dcx().emit_fatal(errors::DeleteOld { name, path: path_buf, err }), } let mut encoder = match FileEncoder::new(&path_buf) { Ok(encoder) => encoder, - Err(err) => { - sess.dcx().emit_err(errors::CreateNew { name, path: path_buf, err }); - return; - } + Err(err) => sess.dcx().emit_fatal(errors::CreateNew { name, path: path_buf, err }), }; write_file_header(&mut encoder, sess); @@ -80,9 +74,7 @@ where ); debug!("save: data written to disk successfully"); } - Err((path, err)) => { - sess.dcx().emit_err(errors::WriteNew { name, path, err }); - } + Err((path, err)) => sess.dcx().emit_fatal(errors::WriteNew { name, path, err }), } } diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index 11ab86277c1..c7cab048db1 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -5,7 +5,7 @@ //! Freshening is used primarily to get a good type for inserting into a cache. The result //! summarizes what the type inferencer knows "so far". The primary place it is used right now is //! in the trait matching algorithm, which needs to be able to cache whether an `impl` self type -//! matches some other type X -- *without* affecting `X`. That means if that if the type `X` is in +//! matches some other type X -- *without* affecting `X`. That means that if the type `X` is in //! fact an unbound type variable, we want the match to be regarded as ambiguous, because depending //! on what type that type variable is ultimately assigned, the match may or may not succeed. //! @@ -21,7 +21,7 @@ //! Because of the manipulation required to handle closures, doing arbitrary operations on //! freshened types is not recommended. However, in addition to doing equality/hash //! comparisons (for caching), it is possible to do a `ty::_match` operation between -//! 2 freshened types - this works even with the closure encoding. +//! two freshened types - this works even with the closure encoding. //! //! __An important detail concerning regions.__ The freshener also replaces *all* free regions with //! 'erased. The reason behind this is that, in general, we do not take region relationships into diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 1ea3db26e21..07bbe78dc2d 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -332,7 +332,7 @@ impl Compiler { // the global context. _timer = Some(self.sess.timer("free_global_ctxt")); if let Err((path, error)) = queries.finish() { - self.sess.dcx().emit_err(errors::FailedWritingFile { path: &path, error }); + self.sess.dcx().emit_fatal(errors::FailedWritingFile { path: &path, error }); } ret diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 399e6968fae..e35d1ee0461 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2817,8 +2817,8 @@ declare_lint! { /// [`ptr::from_exposed_addr`]. /// /// [issue #95228]: https://github.com/rust-lang/rust/issues/95228 - /// [`ptr::with_addr`]: https://doc.rust-lang.org/core/ptr/fn.with_addr - /// [`ptr::from_exposed_addr`]: https://doc.rust-lang.org/core/ptr/fn.from_exposed_addr + /// [`ptr::with_addr`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.with_addr + /// [`ptr::from_exposed_addr`]: https://doc.rust-lang.org/core/ptr/fn.from_exposed_addr.html pub FUZZY_PROVENANCE_CASTS, Allow, "a fuzzy integer to pointer cast is used", @@ -2863,8 +2863,8 @@ declare_lint! { /// about the semantics. /// /// [issue #95228]: https://github.com/rust-lang/rust/issues/95228 - /// [`ptr::addr`]: https://doc.rust-lang.org/core/ptr/fn.addr - /// [`ptr::expose_addr`]: https://doc.rust-lang.org/core/ptr/fn.expose_addr + /// [`ptr::addr`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.addr + /// [`ptr::expose_addr`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.expose_addr pub LOSSY_PROVENANCE_CASTS, Allow, "a lossy pointer to integer cast is used", diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index aca7a66596e..5b296c098bc 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2255,12 +2255,12 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) { // If we forget this, compilation can succeed with an incomplete rmeta file, // causing an ICE when the rmeta file is read by another compilation. if let Err((path, err)) = ecx.opaque.finish() { - tcx.dcx().emit_err(FailWriteFile { path: &path, err }); + tcx.dcx().emit_fatal(FailWriteFile { path: &path, err }); } let file = ecx.opaque.file(); if let Err(err) = encode_root_position(file, root.position.get()) { - tcx.dcx().emit_err(FailWriteFile { path: ecx.opaque.path(), err }); + tcx.dcx().emit_fatal(FailWriteFile { path: ecx.opaque.path(), err }); } // Record metadata size for self-profiling diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 8e7aaee065f..0b487eae36d 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -520,7 +520,7 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn io::Write) -> io: let kind = tcx.def_kind(def_id); let is_function = match kind { DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) => true, - _ => tcx.is_closure(def_id), + _ => tcx.is_closure_or_coroutine(def_id), }; match (kind, body.source.promoted) { (_, Some(i)) => write!(w, "{i:?} in ")?, diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index 8c29bc5a428..8ff5b135aca 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -197,7 +197,7 @@ pub struct ClosureTypeInfo<'tcx> { } fn closure_typeinfo<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ClosureTypeInfo<'tcx> { - debug_assert!(tcx.is_closure(def.to_def_id())); + debug_assert!(tcx.is_closure_or_coroutine(def.to_def_id())); let typeck_results = tcx.typeck(def); let user_provided_sig = typeck_results.user_provided_sigs[&def]; let captures = typeck_results.closure_min_captures_flattened(def); @@ -217,7 +217,7 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn closure_captures(self, def_id: LocalDefId) -> &'tcx [&'tcx ty::CapturedPlace<'tcx>] { - if !self.is_closure(def_id.to_def_id()) { + if !self.is_closure_or_coroutine(def_id.to_def_id()) { return &[]; }; self.closure_typeinfo(def_id).captures diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 1b6d59ab257..2ac3cddfa15 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -426,7 +426,10 @@ impl<'tcx> Instance<'tcx> { ) -> Option<Instance<'tcx>> { debug!("resolve(def_id={:?}, args={:?})", def_id, args); // Use either `resolve_closure` or `resolve_for_vtable` - assert!(!tcx.is_closure(def_id), "Called `resolve_for_fn_ptr` on closure: {def_id:?}"); + assert!( + !tcx.is_closure_or_coroutine(def_id), + "Called `resolve_for_fn_ptr` on closure: {def_id:?}" + ); Instance::resolve(tcx, param_env, def_id, args).ok().flatten().map(|mut resolved| { match resolved.def { InstanceDef::Item(def) if resolved.def.requires_caller_location(tcx) => { @@ -488,7 +491,7 @@ impl<'tcx> Instance<'tcx> { }) ) { - if tcx.is_closure(def) { + if tcx.is_closure_or_coroutine(def) { debug!(" => vtable fn pointer created for closure with #[track_caller]: {:?} for method {:?} {:?}", def, def_id, args); @@ -658,12 +661,10 @@ fn polymorphize<'tcx>( // the unpolymorphized upvar closure would result in a polymorphized closure producing // multiple mono items (and eventually symbol clashes). let def_id = instance.def_id(); - let upvars_ty = if tcx.is_closure(def_id) { - Some(args.as_closure().tupled_upvars_ty()) - } else if tcx.type_of(def_id).skip_binder().is_coroutine() { - Some(args.as_coroutine().tupled_upvars_ty()) - } else { - None + let upvars_ty = match tcx.type_of(def_id).skip_binder().kind() { + ty::Closure(..) => Some(args.as_closure().tupled_upvars_ty()), + ty::Coroutine(..) => Some(args.as_coroutine().tupled_upvars_ty()), + _ => None, }; let has_upvars = upvars_ty.is_some_and(|ty| !ty.tuple_fields().is_empty()); debug!("polymorphize: upvars_ty={:?} has_upvars={:?}", upvars_ty, has_upvars); diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 99384e34222..ebbd02e01bf 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1697,6 +1697,25 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { }) } + fn pretty_print_bound_constness( + &mut self, + trait_ref: ty::TraitRef<'tcx>, + ) -> Result<(), PrintError> { + define_scoped_cx!(self); + + let Some(idx) = self.tcx().generics_of(trait_ref.def_id).host_effect_index else { + return Ok(()); + }; + let arg = trait_ref.args.const_at(idx); + + if arg == self.tcx().consts.false_ { + p!("const "); + } else if arg != self.tcx().consts.true_ && !arg.has_infer() { + p!("~const "); + } + Ok(()) + } + fn should_print_verbose(&self) -> bool { self.tcx().sess.verbose_internals() } @@ -2866,13 +2885,7 @@ define_print_and_forward_display! { } TraitPredPrintModifiersAndPath<'tcx> { - if let Some(idx) = cx.tcx().generics_of(self.0.trait_ref.def_id).host_effect_index - { - let arg = self.0.trait_ref.args.const_at(idx); - if arg != cx.tcx().consts.true_ && !arg.has_infer() { - p!("~const "); - } - } + p!(pretty_print_bound_constness(self.0.trait_ref)); if let ty::ImplPolarity::Negative = self.0.polarity { p!("!") } @@ -2905,11 +2918,7 @@ define_print_and_forward_display! { ty::TraitPredicate<'tcx> { p!(print(self.trait_ref.self_ty()), ": "); - if let Some(idx) = cx.tcx().generics_of(self.trait_ref.def_id).host_effect_index { - if self.trait_ref.args.const_at(idx) != cx.tcx().consts.true_ { - p!("~const "); - } - } + p!(pretty_print_bound_constness(self.trait_ref)); if let ty::ImplPolarity::Negative = self.polarity { p!("!"); } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 5e24b47fbd2..ad2442a7963 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -547,7 +547,7 @@ impl<'tcx> TyCtxt<'tcx> { /// closure appears (and, sadly, a corresponding `NodeId`, since /// those are not yet phased out). The parent of the closure's /// `DefId` will also be the context where it appears. - pub fn is_closure(self, def_id: DefId) -> bool { + pub fn is_closure_or_coroutine(self, def_id: DefId) -> bool { matches!(self.def_kind(def_id), DefKind::Closure) } diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index d2ec5d7d7cc..aa7b6b02f74 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -359,7 +359,7 @@ fn get_body_span<'tcx>( ) -> Span { let mut body_span = hir_body.value.span; - if tcx.is_closure(def_id.to_def_id()) { + if tcx.is_closure_or_coroutine(def_id.to_def_id()) { // If the current function is a closure, and its "body" span was created // by macro expansion or compiler desugaring, try to walk backwards to // the pre-expansion call site or body. diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs index ff6545e9d25..8f6592afe85 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -74,7 +74,7 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>( let expn_span = filtered_statement_span(statement)?; let span = unexpand_into_body_span(expn_span, body_span)?; - Some(CoverageSpan::new(span, expn_span, bcb, is_closure(statement))) + Some(CoverageSpan::new(span, expn_span, bcb, is_closure_or_coroutine(statement))) }); let terminator_span = Some(data.terminator()).into_iter().filter_map(move |terminator| { @@ -88,7 +88,7 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>( }) } -fn is_closure(statement: &Statement<'_>) -> bool { +fn is_closure_or_coroutine(statement: &Statement<'_>) -> bool { match statement.kind { StatementKind::Assign(box (_, Rvalue::Aggregate(box ref agg_kind, _))) => match agg_kind { AggregateKind::Closure(_, _) | AggregateKind::Coroutine(_, _) => true, diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 54464600d99..44beafa0873 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1119,7 +1119,10 @@ fn create_fn_mono_item<'tcx>( source: Span, ) -> Spanned<MonoItem<'tcx>> { let def_id = instance.def_id(); - if tcx.sess.opts.unstable_opts.profile_closures && def_id.is_local() && tcx.is_closure(def_id) { + if tcx.sess.opts.unstable_opts.profile_closures + && def_id.is_local() + && tcx.is_closure_or_coroutine(def_id) + { crate::util::dump_closure_profile(tcx, instance); } diff --git a/compiler/rustc_passes/src/upvars.rs b/compiler/rustc_passes/src/upvars.rs index d87df706cc8..ded20c38543 100644 --- a/compiler/rustc_passes/src/upvars.rs +++ b/compiler/rustc_passes/src/upvars.rs @@ -11,7 +11,7 @@ use rustc_span::Span; pub fn provide(providers: &mut Providers) { providers.upvars_mentioned = |tcx, def_id| { - if !tcx.is_closure(def_id) { + if !tcx.is_closure_or_coroutine(def_id) { return None; } diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 59812efc324..d5883f52819 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -3,9 +3,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(rustdoc_internals)] -// this shouldn't be necessary, but the check for `&mut _` is too naive and denies returning a function pointer that takes a mut ref -#![feature(const_mut_refs)] -#![feature(const_refs_to_cell)] #![feature(min_specialization)] #![feature(never_type)] #![feature(rustc_attrs)] diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 34f2c01f890..51842664eeb 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -44,6 +44,18 @@ enum QueryResult { Poisoned, } +impl QueryResult { + /// Unwraps the query job expecting that it has started. + fn expect_job(self) -> QueryJob { + match self { + Self::Started(job) => job, + Self::Poisoned => { + panic!("job for query failed to start and was poisoned") + } + } + } +} + impl<K> QueryState<K> where K: Eq + Hash + Copy + Debug, @@ -169,10 +181,7 @@ where let job = { let mut lock = state.active.lock_shard_by_value(&key); - match lock.remove(&key).unwrap() { - QueryResult::Started(job) => job, - QueryResult::Poisoned => panic!(), - } + lock.remove(&key).unwrap().expect_job() }; job.signal_complete(); @@ -190,10 +199,8 @@ where let state = self.state; let job = { let mut shard = state.active.lock_shard_by_value(&self.key); - let job = match shard.remove(&self.key).unwrap() { - QueryResult::Started(job) => job, - QueryResult::Poisoned => panic!(), - }; + let job = shard.remove(&self.key).unwrap().expect_job(); + shard.insert(self.key, QueryResult::Poisoned); job }; @@ -277,11 +284,14 @@ where // We didn't find the query result in the query cache. Check if it was // poisoned due to a panic instead. let lock = query.query_state(qcx).active.get_shard_by_value(&key).lock(); + match lock.get(&key) { - // The query we waited on panicked. Continue unwinding here. - Some(QueryResult::Poisoned) => FatalError.raise(), + Some(QueryResult::Poisoned) => { + panic!("query '{}' not cached due to poisoning", query.name()) + } _ => panic!( - "query result must in the cache or the query must be poisoned after a wait" + "query '{}' result must be in the cache or the query must be poisoned after a wait", + query.name() ), } }) diff --git a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs index ba80c23196e..5b91682e168 100644 --- a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs @@ -4,6 +4,7 @@ pub fn target() -> Target { let mut base = base::windows_msvc::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); + base.vendor = "win7".into(); base.add_pre_link_args( LinkerFlavor::Msvc(Lld::No), |
