Auto merge of #99151 - Dylan-DPC:rollup-40aqkxy, r=Dylan-DPC
Rollup of 5 pull requests Successful merges: - #98882 (explain doc comments in macros a bit) - #98907 (Deny float const params even when `adt_const_params` is enabled) - #99091 (Do not mention private types from other crates as impl candidates) - #99140 (Implement `SourceMap::is_span_accessible`) - #99147 (Mention similarly named associated type even if it's not clearly in supertrait) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
9fb32dc924
31 changed files with 348 additions and 96 deletions
|
@ -309,7 +309,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
));
|
||||
|
||||
// Check first whether the source is accessible (issue #87060)
|
||||
if self.infcx.tcx.sess.source_map().span_to_snippet(deref_target).is_ok() {
|
||||
if self.infcx.tcx.sess.source_map().is_span_accessible(deref_target) {
|
||||
err.span_note(deref_target, "deref defined here");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -975,14 +975,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
if self.fn_self_span_reported.insert(fn_span) {
|
||||
err.span_note(
|
||||
// Check whether the source is accessible
|
||||
if self
|
||||
.infcx
|
||||
.tcx
|
||||
.sess
|
||||
.source_map()
|
||||
.span_to_snippet(self_arg.span)
|
||||
.is_ok()
|
||||
{
|
||||
if self.infcx.tcx.sess.source_map().is_span_accessible(self_arg.span) {
|
||||
self_arg.span
|
||||
} else {
|
||||
fn_call_span
|
||||
|
|
|
@ -299,7 +299,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
|
|||
err.note(&format!("attempting to deref into `{}`", deref_target_ty));
|
||||
|
||||
// Check first whether the source is accessible (issue #87060)
|
||||
if tcx.sess.source_map().span_to_snippet(deref_target).is_ok() {
|
||||
if tcx.sess.source_map().is_span_accessible(deref_target) {
|
||||
err.span_note(deref_target, "deref defined here");
|
||||
}
|
||||
|
||||
|
|
|
@ -226,7 +226,7 @@ impl Qualif for CustomEq {
|
|||
// because that component may be part of an enum variant (e.g.,
|
||||
// `Option::<NonStructuralMatchTy>::Some`), in which case some values of this type may be
|
||||
// structural-match (`Option::None`).
|
||||
traits::search_for_structural_match_violation(cx.body.span, cx.tcx, ty).is_some()
|
||||
traits::search_for_structural_match_violation(cx.body.span, cx.tcx, ty, true).is_some()
|
||||
}
|
||||
|
||||
fn in_adt_inherently<'tcx>(
|
||||
|
|
5
compiler/rustc_error_messages/locales/en-US/expand.ftl
Normal file
5
compiler/rustc_error_messages/locales/en-US/expand.ftl
Normal file
|
@ -0,0 +1,5 @@
|
|||
expand-explain-doc-comment-outer =
|
||||
outer doc comments expand to `#[doc = "..."]`, which is what this macro attempted to match
|
||||
|
||||
expand-explain-doc-comment-inner =
|
||||
inner doc comments expand to `#![doc = "..."]`, which is what this macro attempted to match
|
|
@ -33,11 +33,12 @@ pub use unic_langid::{langid, LanguageIdentifier};
|
|||
fluent_messages! {
|
||||
borrowck => "../locales/en-US/borrowck.ftl",
|
||||
builtin_macros => "../locales/en-US/builtin_macros.ftl",
|
||||
const_eval => "../locales/en-US/const_eval.ftl",
|
||||
expand => "../locales/en-US/expand.ftl",
|
||||
lint => "../locales/en-US/lint.ftl",
|
||||
parser => "../locales/en-US/parser.ftl",
|
||||
privacy => "../locales/en-US/privacy.ftl",
|
||||
typeck => "../locales/en-US/typeck.ftl",
|
||||
const_eval => "../locales/en-US/const_eval.ftl",
|
||||
}
|
||||
|
||||
pub use fluent_generated::{self as fluent, DEFAULT_LOCALE_RESOURCES};
|
||||
|
|
|
@ -1558,7 +1558,7 @@ pub fn add_elided_lifetime_in_path_suggestion(
|
|||
insertion_span: Span,
|
||||
) {
|
||||
diag.span_label(path_span, format!("expected lifetime parameter{}", pluralize!(n)));
|
||||
if source_map.span_to_snippet(insertion_span).is_err() {
|
||||
if !source_map.is_span_accessible(insertion_span) {
|
||||
// Do not try to suggest anything if generated by a proc-macro.
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ use rustc_ast::{NodeId, DUMMY_NODE_ID};
|
|||
use rustc_ast_pretty::pprust;
|
||||
use rustc_attr::{self as attr, TransparencyError};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder};
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
|
||||
use rustc_feature::Features;
|
||||
use rustc_lint_defs::builtin::{
|
||||
RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
|
||||
|
@ -25,6 +25,7 @@ use rustc_session::parse::ParseSess;
|
|||
use rustc_session::Session;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::hygiene::Transparency;
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::symbol::{kw, sym, Ident, MacroRulesNormalizedIdent};
|
||||
use rustc_span::Span;
|
||||
|
||||
|
@ -345,7 +346,7 @@ fn expand_macro<'cx>(
|
|||
if !def_span.is_dummy() && !cx.source_map().is_imported(def_span) {
|
||||
err.span_label(cx.source_map().guess_head_span(def_span), "when calling this macro");
|
||||
}
|
||||
|
||||
annotate_doc_comment(&mut err, sess.source_map(), span);
|
||||
// Check whether there's a missing comma in this macro call, like `println!("{}" a);`
|
||||
if let Some((arg, comma_span)) = arg.add_comma() {
|
||||
for lhs in lhses {
|
||||
|
@ -453,7 +454,10 @@ pub fn compile_declarative_macro(
|
|||
Failure(token, msg) => {
|
||||
let s = parse_failure_msg(&token);
|
||||
let sp = token.span.substitute_dummy(def.span);
|
||||
sess.parse_sess.span_diagnostic.struct_span_err(sp, &s).span_label(sp, msg).emit();
|
||||
let mut err = sess.parse_sess.span_diagnostic.struct_span_err(sp, &s);
|
||||
err.span_label(sp, msg);
|
||||
annotate_doc_comment(&mut err, sess.source_map(), sp);
|
||||
err.emit();
|
||||
return dummy_syn_ext();
|
||||
}
|
||||
Error(sp, msg) => {
|
||||
|
@ -590,6 +594,34 @@ pub fn compile_declarative_macro(
|
|||
(mk_syn_ext(expander), rule_spans)
|
||||
}
|
||||
|
||||
#[derive(SessionSubdiagnostic)]
|
||||
enum ExplainDocComment {
|
||||
#[label(expand::explain_doc_comment_inner)]
|
||||
Inner {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[label(expand::explain_doc_comment_outer)]
|
||||
Outer {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
}
|
||||
|
||||
fn annotate_doc_comment(
|
||||
err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
|
||||
sm: &SourceMap,
|
||||
span: Span,
|
||||
) {
|
||||
if let Ok(src) = sm.span_to_snippet(span) {
|
||||
if src.starts_with("///") || src.starts_with("/**") {
|
||||
err.subdiagnostic(ExplainDocComment::Outer { span });
|
||||
} else if src.starts_with("//!") || src.starts_with("/*!") {
|
||||
err.subdiagnostic(ExplainDocComment::Inner { span });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_lhs_nt_follows(sess: &ParseSess, def: &ast::Item, lhs: &mbe::TokenTree) -> bool {
|
||||
// lhs is going to be like TokenTree::Delimited(...), where the
|
||||
// entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens.
|
||||
|
|
|
@ -432,7 +432,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
|
|||
"`let` bindings require an \"irrefutable pattern\", like a `struct` or \
|
||||
an `enum` with only one variant",
|
||||
);
|
||||
if self.tcx.sess.source_map().span_to_snippet(span).is_ok() {
|
||||
if self.tcx.sess.source_map().is_span_accessible(span) {
|
||||
let semi_span = span.shrink_to_hi().with_lo(span.hi() - BytePos(1));
|
||||
let start_span = span.shrink_to_lo();
|
||||
let end_span = semi_span.shrink_to_lo();
|
||||
|
|
|
@ -120,32 +120,37 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn search_for_structural_match_violation(&self, ty: Ty<'tcx>) -> Option<String> {
|
||||
traits::search_for_structural_match_violation(self.span, self.tcx(), ty).map(|non_sm_ty| {
|
||||
with_no_trimmed_paths!(match non_sm_ty.kind {
|
||||
traits::NonStructuralMatchTyKind::Adt(adt) => self.adt_derive_msg(adt),
|
||||
traits::NonStructuralMatchTyKind::Dynamic => {
|
||||
"trait objects cannot be used in patterns".to_string()
|
||||
}
|
||||
traits::NonStructuralMatchTyKind::Opaque => {
|
||||
"opaque types cannot be used in patterns".to_string()
|
||||
}
|
||||
traits::NonStructuralMatchTyKind::Closure => {
|
||||
"closures cannot be used in patterns".to_string()
|
||||
}
|
||||
traits::NonStructuralMatchTyKind::Generator => {
|
||||
"generators cannot be used in patterns".to_string()
|
||||
}
|
||||
traits::NonStructuralMatchTyKind::Param => {
|
||||
bug!("use of a constant whose type is a parameter inside a pattern")
|
||||
}
|
||||
traits::NonStructuralMatchTyKind::Projection => {
|
||||
bug!("use of a constant whose type is a projection inside a pattern")
|
||||
}
|
||||
traits::NonStructuralMatchTyKind::Foreign => {
|
||||
bug!("use of a value of a foreign type inside a pattern")
|
||||
}
|
||||
})
|
||||
})
|
||||
traits::search_for_structural_match_violation(self.span, self.tcx(), ty, true).map(
|
||||
|non_sm_ty| {
|
||||
with_no_trimmed_paths!(match non_sm_ty.kind {
|
||||
traits::NonStructuralMatchTyKind::Adt(adt) => self.adt_derive_msg(adt),
|
||||
traits::NonStructuralMatchTyKind::Dynamic => {
|
||||
"trait objects cannot be used in patterns".to_string()
|
||||
}
|
||||
traits::NonStructuralMatchTyKind::Opaque => {
|
||||
"opaque types cannot be used in patterns".to_string()
|
||||
}
|
||||
traits::NonStructuralMatchTyKind::Closure => {
|
||||
"closures cannot be used in patterns".to_string()
|
||||
}
|
||||
traits::NonStructuralMatchTyKind::Generator => {
|
||||
"generators cannot be used in patterns".to_string()
|
||||
}
|
||||
traits::NonStructuralMatchTyKind::Float => {
|
||||
"floating-point numbers cannot be used in patterns".to_string()
|
||||
}
|
||||
traits::NonStructuralMatchTyKind::Param => {
|
||||
bug!("use of a constant whose type is a parameter inside a pattern")
|
||||
}
|
||||
traits::NonStructuralMatchTyKind::Projection => {
|
||||
bug!("use of a constant whose type is a projection inside a pattern")
|
||||
}
|
||||
traits::NonStructuralMatchTyKind::Foreign => {
|
||||
bug!("use of a value of a foreign type inside a pattern")
|
||||
}
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool {
|
||||
|
|
|
@ -1647,7 +1647,7 @@ impl<'a> Resolver<'a> {
|
|||
|
||||
fn binding_description(&self, b: &NameBinding<'_>, ident: Ident, from_prelude: bool) -> String {
|
||||
let res = b.res();
|
||||
if b.span.is_dummy() || self.session.source_map().span_to_snippet(b.span).is_err() {
|
||||
if b.span.is_dummy() || !self.session.source_map().is_span_accessible(b.span) {
|
||||
// These already contain the "built-in" prefix or look bad with it.
|
||||
let add_built_in =
|
||||
!matches!(b.res(), Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod);
|
||||
|
|
|
@ -597,6 +597,13 @@ impl SourceMap {
|
|||
local_begin.sf.src.is_some() && local_end.sf.src.is_some()
|
||||
}
|
||||
|
||||
pub fn is_span_accessible(&self, sp: Span) -> bool {
|
||||
self.span_to_source(sp, |src, start_index, end_index| {
|
||||
Ok(src.get(start_index..end_index).is_some())
|
||||
})
|
||||
.map_or(false, |is_accessible| is_accessible)
|
||||
}
|
||||
|
||||
/// Returns the source snippet as `String` corresponding to the given `Span`.
|
||||
pub fn span_to_snippet(&self, sp: Span) -> Result<String, SpanSnippetError> {
|
||||
self.span_to_source(sp, |src, start_index, end_index| {
|
||||
|
|
|
@ -673,6 +673,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
if !self.report_similar_impl_candidates(
|
||||
impl_candidates,
|
||||
trait_ref,
|
||||
obligation.cause.body_id,
|
||||
&mut err,
|
||||
) {
|
||||
// This is *almost* equivalent to
|
||||
|
@ -707,6 +708,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
self.report_similar_impl_candidates(
|
||||
impl_candidates,
|
||||
trait_ref,
|
||||
obligation.cause.body_id,
|
||||
&mut err,
|
||||
);
|
||||
}
|
||||
|
@ -1353,6 +1355,7 @@ trait InferCtxtPrivExt<'hir, 'tcx> {
|
|||
&self,
|
||||
impl_candidates: Vec<ImplCandidate<'tcx>>,
|
||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
body_id: hir::HirId,
|
||||
err: &mut Diagnostic,
|
||||
) -> bool;
|
||||
|
||||
|
@ -1735,6 +1738,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
|
|||
&self,
|
||||
impl_candidates: Vec<ImplCandidate<'tcx>>,
|
||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
body_id: hir::HirId,
|
||||
err: &mut Diagnostic,
|
||||
) -> bool {
|
||||
let report = |mut candidates: Vec<TraitRef<'tcx>>, err: &mut Diagnostic| {
|
||||
|
@ -1805,8 +1809,24 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
|
|||
|| self.tcx.is_builtin_derive(def_id)
|
||||
})
|
||||
.filter_map(|def_id| self.tcx.impl_trait_ref(def_id))
|
||||
// Avoid mentioning type parameters.
|
||||
.filter(|trait_ref| !matches!(trait_ref.self_ty().kind(), ty::Param(_)))
|
||||
.filter(|trait_ref| {
|
||||
let self_ty = trait_ref.self_ty();
|
||||
// Avoid mentioning type parameters.
|
||||
if let ty::Param(_) = self_ty.kind() {
|
||||
false
|
||||
}
|
||||
// Avoid mentioning types that are private to another crate
|
||||
else if let ty::Adt(def, _) = self_ty.peel_refs().kind() {
|
||||
// FIXME(compiler-errors): This could be generalized, both to
|
||||
// be more granular, and probably look past other `#[fundamental]`
|
||||
// types, too.
|
||||
self.tcx
|
||||
.visibility(def.did())
|
||||
.is_accessible_from(body_id.owner.to_def_id(), self.tcx)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
return report(normalized_impl_candidates, err);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ pub enum NonStructuralMatchTyKind<'tcx> {
|
|||
Closure,
|
||||
Generator,
|
||||
Projection,
|
||||
Float,
|
||||
}
|
||||
|
||||
/// This method traverses the structure of `ty`, trying to find an
|
||||
|
@ -53,12 +54,16 @@ pub enum NonStructuralMatchTyKind<'tcx> {
|
|||
/// For more background on why Rust has this requirement, and issues
|
||||
/// that arose when the requirement was not enforced completely, see
|
||||
/// Rust RFC 1445, rust-lang/rust#61188, and rust-lang/rust#62307.
|
||||
///
|
||||
/// The floats_allowed flag is used to deny constants in floating point
|
||||
pub fn search_for_structural_match_violation<'tcx>(
|
||||
span: Span,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
floats_allowed: bool,
|
||||
) -> Option<NonStructuralMatchTy<'tcx>> {
|
||||
ty.visit_with(&mut Search { tcx, span, seen: FxHashSet::default() }).break_value()
|
||||
ty.visit_with(&mut Search { tcx, span, seen: FxHashSet::default(), floats_allowed })
|
||||
.break_value()
|
||||
}
|
||||
|
||||
/// This method returns true if and only if `adt_ty` itself has been marked as
|
||||
|
@ -119,6 +124,8 @@ struct Search<'tcx> {
|
|||
/// Tracks ADTs previously encountered during search, so that
|
||||
/// we will not recur on them again.
|
||||
seen: FxHashSet<hir::def_id::DefId>,
|
||||
|
||||
floats_allowed: bool,
|
||||
}
|
||||
|
||||
impl<'tcx> Search<'tcx> {
|
||||
|
@ -192,13 +199,24 @@ impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
|
|||
// for empty array.
|
||||
return ControlFlow::CONTINUE;
|
||||
}
|
||||
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => {
|
||||
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Str | ty::Never => {
|
||||
// These primitive types are always structural match.
|
||||
//
|
||||
// `Never` is kind of special here, but as it is not inhabitable, this should be fine.
|
||||
return ControlFlow::CONTINUE;
|
||||
}
|
||||
|
||||
ty::Float(_) => {
|
||||
if self.floats_allowed {
|
||||
return ControlFlow::CONTINUE;
|
||||
} else {
|
||||
return ControlFlow::Break(NonStructuralMatchTy {
|
||||
ty,
|
||||
kind: NonStructuralMatchTyKind::Float,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ty::Array(..) | ty::Slice(_) | ty::Ref(..) | ty::Tuple(..) => {
|
||||
// First check all contained types and then tell the caller to continue searching.
|
||||
return ty.super_visit_with(self);
|
||||
|
|
|
@ -164,10 +164,62 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
suggested_name,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
err.span_label(span, format!("associated type `{}` not found", assoc_name));
|
||||
return err.emit();
|
||||
}
|
||||
|
||||
// If we didn't find a good item in the supertraits (or couldn't get
|
||||
// the supertraits), like in ItemCtxt, then look more generally from
|
||||
// all visible traits. If there's one clear winner, just suggest that.
|
||||
|
||||
let visible_traits: Vec<_> = self
|
||||
.tcx()
|
||||
.all_traits()
|
||||
.filter(|trait_def_id| {
|
||||
let viz = self.tcx().visibility(*trait_def_id);
|
||||
if let Some(def_id) = self.item_def_id() {
|
||||
viz.is_accessible_from(def_id, self.tcx())
|
||||
} else {
|
||||
viz.is_visible_locally()
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let wider_candidate_names: Vec<_> = visible_traits
|
||||
.iter()
|
||||
.flat_map(|trait_def_id| {
|
||||
self.tcx().associated_items(*trait_def_id).in_definition_order()
|
||||
})
|
||||
.filter_map(
|
||||
|item| if item.kind == ty::AssocKind::Type { Some(item.name) } else { None },
|
||||
)
|
||||
.collect();
|
||||
|
||||
if let (Some(suggested_name), true) = (
|
||||
find_best_match_for_name(&wider_candidate_names, assoc_name.name, None),
|
||||
assoc_name.span != DUMMY_SP,
|
||||
) {
|
||||
if let [best_trait] = visible_traits
|
||||
.iter()
|
||||
.filter(|trait_def_id| {
|
||||
self.tcx()
|
||||
.associated_items(*trait_def_id)
|
||||
.filter_by_name_unhygienic(suggested_name)
|
||||
.any(|item| item.kind == ty::AssocKind::Type)
|
||||
})
|
||||
.collect::<Vec<_>>()[..]
|
||||
{
|
||||
err.span_label(
|
||||
assoc_name.span,
|
||||
format!(
|
||||
"there is a similarly named associated type `{suggested_name}` in the trait `{}`",
|
||||
self.tcx().def_path_str(*best_trait)
|
||||
),
|
||||
);
|
||||
return err.emit();
|
||||
}
|
||||
}
|
||||
|
||||
err.span_label(span, format!("associated type `{}` not found", assoc_name));
|
||||
err.emit()
|
||||
}
|
||||
|
||||
|
|
|
@ -760,7 +760,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
if let Some(call_span) =
|
||||
iter::successors(Some(expr.span), |s| s.parent_callsite())
|
||||
.find(|&s| sp.contains(s))
|
||||
&& sm.span_to_snippet(call_span).is_ok()
|
||||
&& sm.is_span_accessible(call_span)
|
||||
{
|
||||
return Some((
|
||||
sp.with_hi(call_span.lo()),
|
||||
|
@ -773,7 +773,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
return None;
|
||||
}
|
||||
if sp.contains(expr.span)
|
||||
&& sm.span_to_snippet(expr.span).is_ok()
|
||||
&& sm.is_span_accessible(expr.span)
|
||||
{
|
||||
return Some((
|
||||
sp.with_hi(expr.span.lo()),
|
||||
|
|
|
@ -824,50 +824,62 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
|
|||
}
|
||||
|
||||
if let Some(non_structural_match_ty) =
|
||||
traits::search_for_structural_match_violation(param.span, tcx, ty)
|
||||
traits::search_for_structural_match_violation(param.span, tcx, ty, false)
|
||||
{
|
||||
// We use the same error code in both branches, because this is really the same
|
||||
// issue: we just special-case the message for type parameters to make it
|
||||
// clearer.
|
||||
if let ty::Param(_) = ty.peel_refs().kind() {
|
||||
// Const parameters may not have type parameters as their types,
|
||||
// because we cannot be sure that the type parameter derives `PartialEq`
|
||||
// and `Eq` (just implementing them is not enough for `structural_match`).
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
hir_ty.span,
|
||||
E0741,
|
||||
"`{}` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be \
|
||||
used as the type of a const parameter",
|
||||
ty,
|
||||
)
|
||||
.span_label(
|
||||
hir_ty.span,
|
||||
format!("`{}` may not derive both `PartialEq` and `Eq`", ty),
|
||||
)
|
||||
.note(
|
||||
"it is not currently possible to use a type parameter as the type of a \
|
||||
const parameter",
|
||||
)
|
||||
.emit();
|
||||
} else {
|
||||
let mut diag = struct_span_err!(
|
||||
tcx.sess,
|
||||
hir_ty.span,
|
||||
E0741,
|
||||
"`{}` must be annotated with `#[derive(PartialEq, Eq)]` to be used as \
|
||||
the type of a const parameter",
|
||||
non_structural_match_ty.ty,
|
||||
);
|
||||
|
||||
if ty == non_structural_match_ty.ty {
|
||||
diag.span_label(
|
||||
match ty.peel_refs().kind() {
|
||||
ty::Param(_) => {
|
||||
// Const parameters may not have type parameters as their types,
|
||||
// because we cannot be sure that the type parameter derives `PartialEq`
|
||||
// and `Eq` (just implementing them is not enough for `structural_match`).
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
hir_ty.span,
|
||||
format!("`{ty}` doesn't derive both `PartialEq` and `Eq`"),
|
||||
);
|
||||
E0741,
|
||||
"`{ty}` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be \
|
||||
used as the type of a const parameter",
|
||||
)
|
||||
.span_label(
|
||||
hir_ty.span,
|
||||
format!("`{ty}` may not derive both `PartialEq` and `Eq`"),
|
||||
)
|
||||
.note(
|
||||
"it is not currently possible to use a type parameter as the type of a \
|
||||
const parameter",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
ty::Float(_) => {
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
hir_ty.span,
|
||||
E0741,
|
||||
"`{ty}` is forbidden as the type of a const generic parameter",
|
||||
)
|
||||
.note("floats do not derive `Eq` or `Ord`, which are required for const parameters")
|
||||
.emit();
|
||||
}
|
||||
_ => {
|
||||
let mut diag = struct_span_err!(
|
||||
tcx.sess,
|
||||
hir_ty.span,
|
||||
E0741,
|
||||
"`{}` must be annotated with `#[derive(PartialEq, Eq)]` to be used as \
|
||||
the type of a const parameter",
|
||||
non_structural_match_ty.ty,
|
||||
);
|
||||
|
||||
diag.emit();
|
||||
if ty == non_structural_match_ty.ty {
|
||||
diag.span_label(
|
||||
hir_ty.span,
|
||||
format!("`{ty}` doesn't derive both `PartialEq` and `Eq`"),
|
||||
);
|
||||
}
|
||||
|
||||
diag.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -812,7 +812,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
|
|||
/// Builds the `type defined here` message.
|
||||
fn show_definition(&self, err: &mut Diagnostic) {
|
||||
let mut spans: MultiSpan = if let Some(def_span) = self.tcx.def_ident_span(self.def_id) {
|
||||
if self.tcx.sess.source_map().span_to_snippet(def_span).is_ok() {
|
||||
if self.tcx.sess.source_map().is_span_accessible(def_span) {
|
||||
def_span.into()
|
||||
} else {
|
||||
return;
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
error[E0741]: `f32` is forbidden as the type of a const generic parameter
|
||||
--> $DIR/float-generic.rs:5:17
|
||||
|
|
||||
LL | fn foo<const F: f32>() {}
|
||||
| ^^^
|
||||
|
|
||||
= note: floats do not derive `Eq` or `Ord`, which are required for const parameters
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0741`.
|
12
src/test/ui/const-generics/float-generic.rs
Normal file
12
src/test/ui/const-generics/float-generic.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
// revisions: simple adt_const_params
|
||||
#![cfg_attr(adt_const_params, feature(adt_const_params))]
|
||||
#![cfg_attr(adt_const_params, allow(incomplete_features))]
|
||||
|
||||
fn foo<const F: f32>() {}
|
||||
//~^ ERROR `f32` is forbidden as the type of a const generic parameter
|
||||
|
||||
const C: f32 = 1.0;
|
||||
|
||||
fn main() {
|
||||
foo::<C>();
|
||||
}
|
11
src/test/ui/const-generics/float-generic.simple.stderr
Normal file
11
src/test/ui/const-generics/float-generic.simple.stderr
Normal file
|
@ -0,0 +1,11 @@
|
|||
error: `f32` is forbidden as the type of a const generic parameter
|
||||
--> $DIR/float-generic.rs:5:17
|
||||
|
|
||||
LL | fn foo<const F: f32>() {}
|
||||
| ^^^
|
||||
|
|
||||
= note: the only supported types are integers, `bool` and `char`
|
||||
= help: more complex types are supported with `#![feature(adt_const_params)]`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
|
@ -5,7 +5,10 @@ LL | macro_rules! outer {
|
|||
| ------------------ when calling this macro
|
||||
...
|
||||
LL | //! Inner
|
||||
| ^^^^^^^^^ no rules expected this token in macro call
|
||||
| ^^^^^^^^^
|
||||
| |
|
||||
| no rules expected this token in macro call
|
||||
| inner doc comments expand to `#![doc = "..."]`, which is what this macro attempted to match
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -5,7 +5,10 @@ LL | macro_rules! inner {
|
|||
| ------------------ when calling this macro
|
||||
...
|
||||
LL | /// Outer
|
||||
| ^^^^^^^^^ no rules expected this token in macro call
|
||||
| ^^^^^^^^^
|
||||
| |
|
||||
| no rules expected this token in macro call
|
||||
| outer doc comments expand to `#[doc = "..."]`, which is what this macro attempted to match
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
12
src/test/ui/resolve/issue-55673.rs
Normal file
12
src/test/ui/resolve/issue-55673.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
trait Foo {
|
||||
type Bar;
|
||||
}
|
||||
|
||||
fn foo<T: Foo>()
|
||||
where
|
||||
T::Baa: std::fmt::Debug,
|
||||
//~^ ERROR associated type `Baa` not found for `T`
|
||||
{
|
||||
}
|
||||
|
||||
fn main() {}
|
9
src/test/ui/resolve/issue-55673.stderr
Normal file
9
src/test/ui/resolve/issue-55673.stderr
Normal file
|
@ -0,0 +1,9 @@
|
|||
error[E0220]: associated type `Baa` not found for `T`
|
||||
--> $DIR/issue-55673.rs:7:8
|
||||
|
|
||||
LL | T::Baa: std::fmt::Debug,
|
||||
| ^^^ there is a similarly named associated type `Bar` in the trait `Foo`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0220`.
|
11
src/test/ui/suggestions/auxiliary/meow.rs
Normal file
11
src/test/ui/suggestions/auxiliary/meow.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
pub trait Meow {
|
||||
fn meow(&self) {}
|
||||
}
|
||||
|
||||
pub struct GlobalMeow;
|
||||
|
||||
impl Meow for GlobalMeow {}
|
||||
|
||||
pub(crate) struct PrivateMeow;
|
||||
|
||||
impl Meow for PrivateMeow {}
|
16
src/test/ui/suggestions/issue-99080.rs
Normal file
16
src/test/ui/suggestions/issue-99080.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
// aux-build:meow.rs
|
||||
|
||||
extern crate meow;
|
||||
|
||||
use meow::Meow;
|
||||
|
||||
fn needs_meow<T: Meow>(t: T) {}
|
||||
|
||||
fn main() {
|
||||
needs_meow(1usize);
|
||||
//~^ ERROR the trait bound `usize: Meow` is not satisfied
|
||||
}
|
||||
|
||||
struct LocalMeow;
|
||||
|
||||
impl Meow for LocalMeow {}
|
20
src/test/ui/suggestions/issue-99080.stderr
Normal file
20
src/test/ui/suggestions/issue-99080.stderr
Normal file
|
@ -0,0 +1,20 @@
|
|||
error[E0277]: the trait bound `usize: Meow` is not satisfied
|
||||
--> $DIR/issue-99080.rs:10:16
|
||||
|
|
||||
LL | needs_meow(1usize);
|
||||
| ---------- ^^^^^^ the trait `Meow` is not implemented for `usize`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the following other types implement trait `Meow`:
|
||||
GlobalMeow
|
||||
LocalMeow
|
||||
note: required by a bound in `needs_meow`
|
||||
--> $DIR/issue-99080.rs:7:18
|
||||
|
|
||||
LL | fn needs_meow<T: Meow>(t: T) {}
|
||||
| ^^^^ required by this bound in `needs_meow`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
|
@ -15,7 +15,6 @@ LL | s.strip_suffix(b'\n').unwrap_or(s)
|
|||
&'c &'b str
|
||||
[char; N]
|
||||
char
|
||||
pattern::MultiCharEqPattern<C>
|
||||
= note: required because of the requirements on the impl of `Pattern<'_>` for `u8`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
|
|
@ -2,13 +2,13 @@ error[E0220]: associated type `Res` not found for `Self`
|
|||
--> $DIR/issue-59029-1.rs:5:52
|
||||
|
|
||||
LL | trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
|
||||
| ^^^ associated type `Res` not found
|
||||
| ^^^ there is a similarly named associated type `Res` in the trait `Svc`
|
||||
|
||||
error[E0220]: associated type `Res` not found for `Self`
|
||||
--> $DIR/issue-59029-1.rs:5:52
|
||||
|
|
||||
LL | trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
|
||||
| ^^^ associated type `Res` not found
|
||||
| ^^^ there is a similarly named associated type `Res` in the trait `Svc`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0220]: associated type `Assoc` not found for `V`
|
|||
--> $DIR/not_well_formed.rs:9:29
|
||||
|
|
||||
LL | type Foo<V> = impl Trait<V::Assoc>;
|
||||
| ^^^^^ associated type `Assoc` not found
|
||||
| ^^^^^ there is a similarly named associated type `Assoc` in the trait `TraitWithAssoc`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue