diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_lint/src/map_unit_fn.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/query/keys.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_monomorphize/src/polymorphize.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_passes/Cargo.toml | 1 | ||||
| -rw-r--r-- | compiler/rustc_passes/messages.ftl | 21 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/check_attr.rs | 173 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/errors.rs | 45 |
8 files changed, 114 insertions, 160 deletions
diff --git a/compiler/rustc_lint/src/map_unit_fn.rs b/compiler/rustc_lint/src/map_unit_fn.rs index 62e8b4fe9e4..7c692fee333 100644 --- a/compiler/rustc_lint/src/map_unit_fn.rs +++ b/compiler/rustc_lint/src/map_unit_fn.rs @@ -56,6 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for MapUnitFn { return; } let arg_ty = cx.typeck_results().expr_ty(&args[0]); + let default_span = args[0].span; if let ty::FnDef(id, _) = arg_ty.kind() { let fn_ty = cx.tcx.fn_sig(id).skip_binder(); let ret_ty = fn_ty.output().skip_binder(); @@ -64,7 +65,10 @@ impl<'tcx> LateLintPass<'tcx> for MapUnitFn { MAP_UNIT_FN, span, MappingToUnit { - function_label: cx.tcx.span_of_impl(*id).unwrap(), + function_label: cx + .tcx + .span_of_impl(*id) + .unwrap_or(default_span), argument_label: args[0].span, map_label: arg_ty.default_span(cx.tcx), suggestion: path.ident.span, @@ -80,7 +84,10 @@ impl<'tcx> LateLintPass<'tcx> for MapUnitFn { MAP_UNIT_FN, span, MappingToUnit { - function_label: cx.tcx.span_of_impl(*id).unwrap(), + function_label: cx + .tcx + .span_of_impl(*id) + .unwrap_or(default_span), argument_label: args[0].span, map_label: arg_ty.default_span(cx.tcx), suggestion: path.ident.span, diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 6c5e8863010..a9843395336 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -226,7 +226,15 @@ provide! { tcx, def_id, other, cdata, lookup_default_body_stability => { table } lookup_deprecation_entry => { table } params_in_repr => { table } - unused_generic_params => { table } + // FIXME: Could be defaulted, but `LazyValue<UnusedGenericParams>` is not `FixedSizeEncoding`.. + unused_generic_params => { + cdata + .root + .tables + .unused_generic_params + .get(cdata, def_id.index) + .map_or_else(|| ty::UnusedGenericParams::new_all_used(), |lazy| lazy.decode((cdata, tcx))) + } opt_def_kind => { table_direct } impl_parent => { table } impl_polarity => { table_direct } diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index 78ee8a6a8fd..6e961a775c1 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -63,7 +63,7 @@ impl<'tcx> Key for ty::InstanceDef<'tcx> { #[inline(always)] fn query_crate_is_local(&self) -> bool { - true + self.def_id().is_local() } fn default_span(&self, tcx: TyCtxt<'_>) -> Span { @@ -76,7 +76,7 @@ impl<'tcx> Key for ty::Instance<'tcx> { #[inline(always)] fn query_crate_is_local(&self) -> bool { - true + self.def_id().is_local() } fn default_span(&self, tcx: TyCtxt<'_>) -> Span { diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index b7c3dbcc091..63263a642ac 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -36,6 +36,8 @@ fn unused_generic_params<'tcx>( tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>, ) -> UnusedGenericParams { + assert!(instance.def_id().is_local()); + if !tcx.sess.opts.unstable_opts.polymorphize { // If polymorphization disabled, then all parameters are used. return UnusedGenericParams::new_all_used(); @@ -100,13 +102,6 @@ fn should_polymorphize<'tcx>( return false; } - // Polymorphization results are stored in cross-crate metadata only when there are unused - // parameters, so assume that non-local items must have only used parameters (else this query - // would not be invoked, and the cross-crate metadata used instead). - if !def_id.is_local() { - return false; - } - // Foreign items have no bodies to analyze. if tcx.is_foreign_item(def_id) { return false; diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml index faa9c493d88..44f991f8c15 100644 --- a/compiler/rustc_passes/Cargo.toml +++ b/compiler/rustc_passes/Cargo.toml @@ -22,3 +22,4 @@ rustc_span = { path = "../rustc_span" } rustc_lexer = { path = "../rustc_lexer" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_feature = { path = "../rustc_feature" } +rustc_trait_selection = { path = "../rustc_trait_selection" } diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 3fa78efc290..d063b51c8b8 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -720,26 +720,7 @@ passes_ignored_derived_impls = *[other] traits {$trait_list}, but these are } intentionally ignored during dead code analysis -passes_proc_macro_typeerror = mismatched {$kind} signature - .label = found {$found}, expected type `proc_macro::TokenStream` - .note = {$kind}s must have a signature of `{$expected_signature}` - -passes_proc_macro_diff_arg_count = mismatched {$kind} signature - .label = found unexpected {$count -> - [one] argument - *[other] arguments - } - .note = {$kind}s must have a signature of `{$expected_signature}` - -passes_proc_macro_missing_args = mismatched {$kind} signature - .label = {$kind} must have {$expected_input_count -> - [one] one argument - *[other] two arguments - } of type `proc_macro::TokenStream` - -passes_proc_macro_invalid_abi = proc macro functions may not be `extern "{$abi}"` - -passes_proc_macro_unsafe = proc macro functions may not be `unsafe` +passes_proc_macro_bad_sig = {$kind} has incorrect signature passes_skipping_const_checks = skipping const checks diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index c8d371dd084..8bed7888142 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -19,9 +19,10 @@ use rustc_hir::{ use rustc_hir::{MethodKind, Target, Unsafety}; use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault; -use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; +use rustc_middle::traits::ObligationCause; +use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::{ParamEnv, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint::builtin::{ CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS, UNUSED_ATTRIBUTES, @@ -30,6 +31,9 @@ use rustc_session::parse::feature_err; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs}; +use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; +use rustc_trait_selection::traits::ObligationCtxt; use std::cell::Cell; use std::collections::hash_map::Entry; @@ -2188,100 +2192,99 @@ impl CheckAttrVisitor<'_> { /// /// If this best effort goes wrong, it will just emit a worse error later (see #102923) fn check_proc_macro(&self, hir_id: HirId, target: Target, kind: ProcMacroKind) { - let expected_input_count = match kind { - ProcMacroKind::Attribute => 2, - ProcMacroKind::Derive | ProcMacroKind::FunctionLike => 1, - }; - - let expected_signature = match kind { - ProcMacroKind::Attribute => "fn(TokenStream, TokenStream) -> TokenStream", - ProcMacroKind::Derive | ProcMacroKind::FunctionLike => "fn(TokenStream) -> TokenStream", - }; + if target != Target::Fn { + return; + } let tcx = self.tcx; - if target == Target::Fn { - let Some(tokenstream) = tcx.get_diagnostic_item(sym::TokenStream) else {return}; - let tokenstream = tcx.type_of(tokenstream).subst_identity(); - - let id = hir_id.expect_owner(); - let hir_sig = tcx.hir().fn_sig_by_hir_id(hir_id).unwrap(); - - let sig = - tcx.liberate_late_bound_regions(id.to_def_id(), tcx.fn_sig(id).subst_identity()); - let sig = tcx.normalize_erasing_regions(ParamEnv::empty(), sig); - - // We don't currently require that the function signature is equal to - // `fn(TokenStream) -> TokenStream`, but instead monomorphizes to - // `fn(TokenStream) -> TokenStream` after some substitution of generic arguments. - // - // Properly checking this means pulling in additional `rustc` crates, so we don't. - let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsCandidateKey }; - - if sig.abi != Abi::Rust { - tcx.sess.emit_err(errors::ProcMacroInvalidAbi { - span: hir_sig.span, - abi: sig.abi.name(), - }); - self.abort.set(true); - } + let Some(token_stream_def_id) = tcx.get_diagnostic_item(sym::TokenStream) else { return; }; + let Some(token_stream) = tcx.type_of(token_stream_def_id).no_bound_vars() else { return; }; - if sig.unsafety == Unsafety::Unsafe { - tcx.sess.emit_err(errors::ProcMacroUnsafe { span: hir_sig.span }); - self.abort.set(true); - } + let def_id = hir_id.expect_owner().def_id; + let param_env = ty::ParamEnv::empty(); - let output = sig.output(); + let infcx = tcx.infer_ctxt().build(); + let ocx = ObligationCtxt::new(&infcx); - // Typecheck the output - if !drcx.types_may_unify(output, tokenstream) { - tcx.sess.emit_err(errors::ProcMacroTypeError { - span: hir_sig.decl.output.span(), - found: output, - kind, - expected_signature, - }); - self.abort.set(true); - } + let span = tcx.def_span(def_id); + let fresh_substs = infcx.fresh_substs_for_item(span, def_id.to_def_id()); + let sig = tcx.liberate_late_bound_regions( + def_id.to_def_id(), + tcx.fn_sig(def_id).subst(tcx, fresh_substs), + ); - if sig.inputs().len() < expected_input_count { - tcx.sess.emit_err(errors::ProcMacroMissingArguments { - expected_input_count, - span: hir_sig.span, - kind, - expected_signature, - }); - self.abort.set(true); - } + let mut cause = ObligationCause::misc(span, def_id); + let sig = ocx.normalize(&cause, param_env, sig); - // Check that the inputs are correct, if there are enough. - if sig.inputs().len() >= expected_input_count { - for (arg, input) in - sig.inputs().iter().zip(hir_sig.decl.inputs).take(expected_input_count) - { - if !drcx.types_may_unify(*arg, tokenstream) { - tcx.sess.emit_err(errors::ProcMacroTypeError { - span: input.span, - found: *arg, - kind, - expected_signature, - }); - self.abort.set(true); + // proc macro is not WF. + let errors = ocx.select_where_possible(); + if !errors.is_empty() { + return; + } + + let expected_sig = tcx.mk_fn_sig( + std::iter::repeat(token_stream).take(match kind { + ProcMacroKind::Attribute => 2, + ProcMacroKind::Derive | ProcMacroKind::FunctionLike => 1, + }), + token_stream, + false, + Unsafety::Normal, + Abi::Rust, + ); + + if let Err(terr) = ocx.eq(&cause, param_env, expected_sig, sig) { + let mut diag = tcx.sess.create_err(errors::ProcMacroBadSig { span, kind }); + + let hir_sig = tcx.hir().fn_sig_by_hir_id(hir_id); + if let Some(hir_sig) = hir_sig { + match terr { + TypeError::ArgumentMutability(idx) | TypeError::ArgumentSorts(_, idx) => { + if let Some(ty) = hir_sig.decl.inputs.get(idx) { + diag.set_span(ty.span); + cause.span = ty.span; + } else if idx == hir_sig.decl.inputs.len() { + let span = hir_sig.decl.output.span(); + diag.set_span(span); + cause.span = span; + } + } + TypeError::ArgCount => { + if let Some(ty) = hir_sig.decl.inputs.get(expected_sig.inputs().len()) { + diag.set_span(ty.span); + cause.span = ty.span; + } } + TypeError::UnsafetyMismatch(_) => { + // FIXME: Would be nice if we had a span here.. + } + TypeError::AbiMismatch(_) => { + // FIXME: Would be nice if we had a span here.. + } + TypeError::VariadicMismatch(_) => { + // FIXME: Would be nice if we had a span here.. + } + _ => {} } } - // Check that there are not too many arguments - let body_id = tcx.hir().body_owned_by(id.def_id); - let excess = tcx.hir().body(body_id).params.get(expected_input_count..); - if let Some(excess @ [begin @ end] | excess @ [begin, .., end]) = excess { - tcx.sess.emit_err(errors::ProcMacroDiffArguments { - span: begin.span.to(end.span), - count: excess.len(), - kind, - expected_signature, - }); - self.abort.set(true); - } + infcx.err_ctxt().note_type_err( + &mut diag, + &cause, + None, + Some(ValuePairs::Sigs(ExpectedFound { expected: expected_sig, found: sig })), + terr, + false, + false, + ); + diag.emit(); + self.abort.set(true); + } + + let errors = ocx.select_all_or_error(); + if !errors.is_empty() { + infcx.err_ctxt().report_fulfillment_errors(&errors); + self.abort.set(true); } } } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 9f1c0b5a0b7..1b0cd5d91ab 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1546,52 +1546,11 @@ pub struct ChangeFieldsToBeOfUnitType { } #[derive(Diagnostic)] -#[diag(passes_proc_macro_typeerror)] -#[note] -pub(crate) struct ProcMacroTypeError<'tcx> { - #[primary_span] - #[label] - pub span: Span, - pub found: Ty<'tcx>, - pub kind: ProcMacroKind, - pub expected_signature: &'static str, -} - -#[derive(Diagnostic)] -#[diag(passes_proc_macro_diff_arg_count)] -pub(crate) struct ProcMacroDiffArguments { - #[primary_span] - #[label] - pub span: Span, - pub count: usize, - pub kind: ProcMacroKind, - pub expected_signature: &'static str, -} - -#[derive(Diagnostic)] -#[diag(passes_proc_macro_missing_args)] -pub(crate) struct ProcMacroMissingArguments { +#[diag(passes_proc_macro_bad_sig)] +pub(crate) struct ProcMacroBadSig { #[primary_span] - #[label] pub span: Span, - pub expected_input_count: usize, pub kind: ProcMacroKind, - pub expected_signature: &'static str, -} - -#[derive(Diagnostic)] -#[diag(passes_proc_macro_invalid_abi)] -pub(crate) struct ProcMacroInvalidAbi { - #[primary_span] - pub span: Span, - pub abi: &'static str, -} - -#[derive(Diagnostic)] -#[diag(passes_proc_macro_unsafe)] -pub(crate) struct ProcMacroUnsafe { - #[primary_span] - pub span: Span, } #[derive(Diagnostic)] |
