mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Auto merge of #121964 - matthiaskrgr:rollup-rtcju5m, r=matthiaskrgr
Rollup of 3 pull requests Successful merges: - #121130 (Suggest moving definition if non-found macro_rules! is defined later) - #121912 (Properly deal with GATs when looking for method chains to point at) - #121927 (Add a proper `with_no_queries` to printing) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
7606c13961
@ -64,7 +64,7 @@ fn opaque_type_bounds<'tcx>(
|
|||||||
item_ty: Ty<'tcx>,
|
item_ty: Ty<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> &'tcx [(ty::Clause<'tcx>, Span)] {
|
) -> &'tcx [(ty::Clause<'tcx>, Span)] {
|
||||||
ty::print::with_no_queries!({
|
ty::print::with_reduced_queries!({
|
||||||
let icx = ItemCtxt::new(tcx, opaque_def_id);
|
let icx = ItemCtxt::new(tcx, opaque_def_id);
|
||||||
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, PredicateFilter::All);
|
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, PredicateFilter::All);
|
||||||
// Opaque types are implicitly sized unless a `?Sized` bound is found
|
// Opaque types are implicitly sized unless a `?Sized` bound is found
|
||||||
|
@ -64,7 +64,7 @@ thread_local! {
|
|||||||
static SHOULD_PREFIX_WITH_CRATE: Cell<bool> = const { Cell::new(false) };
|
static SHOULD_PREFIX_WITH_CRATE: Cell<bool> = const { Cell::new(false) };
|
||||||
static NO_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) };
|
static NO_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) };
|
||||||
static FORCE_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) };
|
static FORCE_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) };
|
||||||
static NO_QUERIES: Cell<bool> = const { Cell::new(false) };
|
static REDUCED_QUERIES: Cell<bool> = const { Cell::new(false) };
|
||||||
static NO_VISIBLE_PATH: Cell<bool> = const { Cell::new(false) };
|
static NO_VISIBLE_PATH: Cell<bool> = const { Cell::new(false) };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,14 +102,14 @@ macro_rules! define_helper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
define_helper!(
|
define_helper!(
|
||||||
/// Avoids running any queries during any prints that occur
|
/// Avoids running select queries during any prints that occur
|
||||||
/// during the closure. This may alter the appearance of some
|
/// during the closure. This may alter the appearance of some
|
||||||
/// types (e.g. forcing verbose printing for opaque types).
|
/// types (e.g. forcing verbose printing for opaque types).
|
||||||
/// This method is used during some queries (e.g. `explicit_item_bounds`
|
/// This method is used during some queries (e.g. `explicit_item_bounds`
|
||||||
/// for opaque types), to ensure that any debug printing that
|
/// for opaque types), to ensure that any debug printing that
|
||||||
/// occurs during the query computation does not end up recursively
|
/// occurs during the query computation does not end up recursively
|
||||||
/// calling the same query.
|
/// calling the same query.
|
||||||
fn with_no_queries(NoQueriesGuard, NO_QUERIES);
|
fn with_reduced_queries(ReducedQueriesGuard, REDUCED_QUERIES);
|
||||||
/// Force us to name impls with just the filename/line number. We
|
/// Force us to name impls with just the filename/line number. We
|
||||||
/// normally try to use types. But at some points, notably while printing
|
/// normally try to use types. But at some points, notably while printing
|
||||||
/// cycle errors, this can result in extra or suboptimal error output,
|
/// cycle errors, this can result in extra or suboptimal error output,
|
||||||
@ -127,6 +127,15 @@ define_helper!(
|
|||||||
fn with_no_visible_paths(NoVisibleGuard, NO_VISIBLE_PATH);
|
fn with_no_visible_paths(NoVisibleGuard, NO_VISIBLE_PATH);
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// Avoids running any queries during prints.
|
||||||
|
pub macro with_no_queries($e:expr) {{
|
||||||
|
$crate::ty::print::with_reduced_queries!($crate::ty::print::with_forced_impl_filename_line!(
|
||||||
|
$crate::ty::print::with_no_trimmed_paths!($crate::ty::print::with_no_visible_paths!(
|
||||||
|
$crate::ty::print::with_forced_impl_filename_line!($e)
|
||||||
|
))
|
||||||
|
))
|
||||||
|
}}
|
||||||
|
|
||||||
/// The "region highlights" are used to control region printing during
|
/// The "region highlights" are used to control region printing during
|
||||||
/// specific error messages. When a "region highlight" is enabled, it
|
/// specific error messages. When a "region highlight" is enabled, it
|
||||||
/// gives an alternate way to print specific regions. For now, we
|
/// gives an alternate way to print specific regions. For now, we
|
||||||
@ -659,7 +668,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||||||
p!(")")
|
p!(")")
|
||||||
}
|
}
|
||||||
ty::FnDef(def_id, args) => {
|
ty::FnDef(def_id, args) => {
|
||||||
if with_no_queries() {
|
if with_reduced_queries() {
|
||||||
p!(print_def_path(def_id, args));
|
p!(print_def_path(def_id, args));
|
||||||
} else {
|
} else {
|
||||||
let sig = self.tcx().fn_sig(def_id).instantiate(self.tcx(), args);
|
let sig = self.tcx().fn_sig(def_id).instantiate(self.tcx(), args);
|
||||||
@ -759,7 +768,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if with_no_queries() {
|
if with_reduced_queries() {
|
||||||
p!(print_def_path(def_id, &[]));
|
p!(print_def_path(def_id, &[]));
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} else {
|
} else {
|
||||||
@ -1876,7 +1885,8 @@ impl DerefMut for FmtPrinter<'_, '_> {
|
|||||||
|
|
||||||
impl<'a, 'tcx> FmtPrinter<'a, 'tcx> {
|
impl<'a, 'tcx> FmtPrinter<'a, 'tcx> {
|
||||||
pub fn new(tcx: TyCtxt<'tcx>, ns: Namespace) -> Self {
|
pub fn new(tcx: TyCtxt<'tcx>, ns: Namespace) -> Self {
|
||||||
let limit = if with_no_queries() { Limit::new(1048576) } else { tcx.type_length_limit() };
|
let limit =
|
||||||
|
if with_reduced_queries() { Limit::new(1048576) } else { tcx.type_length_limit() };
|
||||||
Self::new_with_limit(tcx, ns, limit)
|
Self::new_with_limit(tcx, ns, limit)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2962,7 +2972,7 @@ define_print_and_forward_display! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TraitRefPrintSugared<'tcx> {
|
TraitRefPrintSugared<'tcx> {
|
||||||
if !with_no_queries()
|
if !with_reduced_queries()
|
||||||
&& let Some(kind) = cx.tcx().fn_trait_kind_from_def_id(self.0.def_id)
|
&& let Some(kind) = cx.tcx().fn_trait_kind_from_def_id(self.0.def_id)
|
||||||
&& let ty::Tuple(args) = self.0.args.type_at(1).kind()
|
&& let ty::Tuple(args) = self.0.args.type_at(1).kind()
|
||||||
{
|
{
|
||||||
@ -3050,7 +3060,7 @@ define_print_and_forward_display! {
|
|||||||
// If we're printing verbosely, or don't want to invoke queries
|
// If we're printing verbosely, or don't want to invoke queries
|
||||||
// (`is_impl_trait_in_trait`), then fall back to printing the def path.
|
// (`is_impl_trait_in_trait`), then fall back to printing the def path.
|
||||||
// This is likely what you want if you're debugging the compiler anyways.
|
// This is likely what you want if you're debugging the compiler anyways.
|
||||||
if !(cx.should_print_verbose() || with_no_queries())
|
if !(cx.should_print_verbose() || with_reduced_queries())
|
||||||
&& cx.tcx().is_impl_trait_in_trait(self.def_id)
|
&& cx.tcx().is_impl_trait_in_trait(self.def_id)
|
||||||
{
|
{
|
||||||
return cx.pretty_print_opaque_impl_type(self.def_id, self.args);
|
return cx.pretty_print_opaque_impl_type(self.def_id, self.args);
|
||||||
|
@ -18,7 +18,7 @@ use rustc_middle::query::on_disk_cache::AbsoluteBytePos;
|
|||||||
use rustc_middle::query::on_disk_cache::{CacheDecoder, CacheEncoder, EncodedDepNodeIndex};
|
use rustc_middle::query::on_disk_cache::{CacheDecoder, CacheEncoder, EncodedDepNodeIndex};
|
||||||
use rustc_middle::query::Key;
|
use rustc_middle::query::Key;
|
||||||
use rustc_middle::ty::tls::{self, ImplicitCtxt};
|
use rustc_middle::ty::tls::{self, ImplicitCtxt};
|
||||||
use rustc_middle::ty::{self, print::with_no_queries, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext};
|
use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext};
|
||||||
use rustc_query_system::ich::StableHashingContext;
|
use rustc_query_system::ich::StableHashingContext;
|
||||||
use rustc_query_system::query::{
|
use rustc_query_system::query::{
|
||||||
@ -305,20 +305,13 @@ pub(crate) fn create_query_frame<
|
|||||||
name: &'static str,
|
name: &'static str,
|
||||||
) -> QueryStackFrame {
|
) -> QueryStackFrame {
|
||||||
// Avoid calling queries while formatting the description
|
// Avoid calling queries while formatting the description
|
||||||
let description = ty::print::with_no_queries!(
|
let description = ty::print::with_no_queries!(do_describe(tcx, key));
|
||||||
// Disable visible paths printing for performance reasons.
|
|
||||||
// Showing visible path instead of any path is not that important in production.
|
|
||||||
ty::print::with_no_visible_paths!(
|
|
||||||
// Force filename-line mode to avoid invoking `type_of` query.
|
|
||||||
ty::print::with_forced_impl_filename_line!(do_describe(tcx, key))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
let description = if tcx.sess.verbose_internals() {
|
let description = if tcx.sess.verbose_internals() {
|
||||||
format!("{description} [{name:?}]")
|
format!("{description} [{name:?}]")
|
||||||
} else {
|
} else {
|
||||||
description
|
description
|
||||||
};
|
};
|
||||||
let span = if kind == dep_graph::dep_kinds::def_span || with_no_queries() {
|
let span = if kind == dep_graph::dep_kinds::def_span {
|
||||||
// The `def_span` query is used to calculate `default_span`,
|
// The `def_span` query is used to calculate `default_span`,
|
||||||
// so exit to avoid infinite recursion.
|
// so exit to avoid infinite recursion.
|
||||||
None
|
None
|
||||||
@ -326,7 +319,7 @@ pub(crate) fn create_query_frame<
|
|||||||
Some(key.default_span(tcx))
|
Some(key.default_span(tcx))
|
||||||
};
|
};
|
||||||
let def_id = key.key_as_def_id();
|
let def_id = key.key_as_def_id();
|
||||||
let def_kind = if kind == dep_graph::dep_kinds::def_kind || with_no_queries() {
|
let def_kind = if kind == dep_graph::dep_kinds::def_kind {
|
||||||
// Try to avoid infinite recursion.
|
// Try to avoid infinite recursion.
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
@ -83,6 +83,10 @@ resolve_consider_declaring_with_pub =
|
|||||||
resolve_consider_marking_as_pub =
|
resolve_consider_marking_as_pub =
|
||||||
consider marking `{$ident}` as `pub` in the imported module
|
consider marking `{$ident}` as `pub` in the imported module
|
||||||
|
|
||||||
|
resolve_consider_move_macro_position =
|
||||||
|
consider moving the definition of `{$ident}` before this call
|
||||||
|
|
||||||
|
|
||||||
resolve_const_not_member_of_trait =
|
resolve_const_not_member_of_trait =
|
||||||
const `{$const_}` is not a member of trait `{$trait_}`
|
const `{$const_}` is not a member of trait `{$trait_}`
|
||||||
.label = not a member of trait `{$trait_}`
|
.label = not a member of trait `{$trait_}`
|
||||||
@ -176,6 +180,9 @@ resolve_lowercase_self =
|
|||||||
attempt to use a non-constant value in a constant
|
attempt to use a non-constant value in a constant
|
||||||
.suggestion = try using `Self`
|
.suggestion = try using `Self`
|
||||||
|
|
||||||
|
resolve_macro_defined_later =
|
||||||
|
a macro with the same name exists, but it appears later at here
|
||||||
|
|
||||||
resolve_macro_expected_found =
|
resolve_macro_expected_found =
|
||||||
expected {$expected}, found {$found} `{$macro_path}`
|
expected {$expected}, found {$found} `{$macro_path}`
|
||||||
|
|
||||||
|
@ -30,7 +30,10 @@ use rustc_span::{BytePos, Span, SyntaxContext};
|
|||||||
use thin_vec::{thin_vec, ThinVec};
|
use thin_vec::{thin_vec, ThinVec};
|
||||||
|
|
||||||
use crate::errors::{AddedMacroUse, ChangeImportBinding, ChangeImportBindingSuggestion};
|
use crate::errors::{AddedMacroUse, ChangeImportBinding, ChangeImportBindingSuggestion};
|
||||||
use crate::errors::{ConsiderAddingADerive, ExplicitUnsafeTraits, MaybeMissingMacroRulesName};
|
use crate::errors::{
|
||||||
|
ConsiderAddingADerive, ExplicitUnsafeTraits, MacroDefinedLater, MacroSuggMovePosition,
|
||||||
|
MaybeMissingMacroRulesName,
|
||||||
|
};
|
||||||
use crate::imports::{Import, ImportKind};
|
use crate::imports::{Import, ImportKind};
|
||||||
use crate::late::{PatternSource, Rib};
|
use crate::late::{PatternSource, Rib};
|
||||||
use crate::{errors as errs, BindingKey};
|
use crate::{errors as errs, BindingKey};
|
||||||
@ -1456,6 +1459,24 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let unused_macro = self.unused_macros.iter().find_map(|(def_id, (_, unused_ident))| {
|
||||||
|
if unused_ident.name == ident.name {
|
||||||
|
Some((def_id.clone(), unused_ident.clone()))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some((def_id, unused_ident)) = unused_macro {
|
||||||
|
let scope = self.local_macro_def_scopes[&def_id];
|
||||||
|
let parent_nearest = parent_scope.module.nearest_parent_mod();
|
||||||
|
if Some(parent_nearest) == scope.opt_def_id() {
|
||||||
|
err.subdiagnostic(self.dcx(), MacroDefinedLater { span: unused_ident.span });
|
||||||
|
err.subdiagnostic(self.dcx(), MacroSuggMovePosition { span: ident.span, ident });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if self.macro_names.contains(&ident.normalize_to_macros_2_0()) {
|
if self.macro_names.contains(&ident.normalize_to_macros_2_0()) {
|
||||||
err.subdiagnostic(self.dcx(), AddedMacroUse);
|
err.subdiagnostic(self.dcx(), AddedMacroUse);
|
||||||
return;
|
return;
|
||||||
|
@ -646,6 +646,21 @@ pub(crate) struct ExplicitUnsafeTraits {
|
|||||||
pub(crate) ident: Ident,
|
pub(crate) ident: Ident,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[note(resolve_macro_defined_later)]
|
||||||
|
pub(crate) struct MacroDefinedLater {
|
||||||
|
#[primary_span]
|
||||||
|
pub(crate) span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[label(resolve_consider_move_macro_position)]
|
||||||
|
pub(crate) struct MacroSuggMovePosition {
|
||||||
|
#[primary_span]
|
||||||
|
pub(crate) span: Span,
|
||||||
|
pub(crate) ident: Ident,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Subdiagnostic)]
|
#[derive(Subdiagnostic)]
|
||||||
#[note(resolve_missing_macro_rules_name)]
|
#[note(resolve_missing_macro_rules_name)]
|
||||||
pub(crate) struct MaybeMissingMacroRulesName {
|
pub(crate) struct MaybeMissingMacroRulesName {
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#![allow(internal_features)]
|
#![allow(internal_features)]
|
||||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||||
#![allow(rustc::untranslatable_diagnostic)]
|
#![allow(rustc::untranslatable_diagnostic)]
|
||||||
|
#![feature(assert_matches)]
|
||||||
#![feature(associated_type_bounds)]
|
#![feature(associated_type_bounds)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(control_flow_enum)]
|
#![feature(control_flow_enum)]
|
||||||
|
@ -38,6 +38,7 @@ use rustc_span::def_id::LocalDefId;
|
|||||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||||
use rustc_span::{BytePos, DesugaringKind, ExpnKind, MacroKind, Span, DUMMY_SP};
|
use rustc_span::{BytePos, DesugaringKind, ExpnKind, MacroKind, Span, DUMMY_SP};
|
||||||
use rustc_target::spec::abi;
|
use rustc_target::spec::abi;
|
||||||
|
use std::assert_matches::debug_assert_matches;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
@ -4219,30 +4220,25 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let origin = TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span };
|
let origin = TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span };
|
||||||
let trait_def_id = proj.trait_def_id(self.tcx);
|
|
||||||
// Make `Self` be equivalent to the type of the call chain
|
// Make `Self` be equivalent to the type of the call chain
|
||||||
// expression we're looking at now, so that we can tell what
|
// expression we're looking at now, so that we can tell what
|
||||||
// for example `Iterator::Item` is at this point in the chain.
|
// for example `Iterator::Item` is at this point in the chain.
|
||||||
let args = GenericArgs::for_item(self.tcx, trait_def_id, |param, _| {
|
let args = GenericArgs::for_item(self.tcx, proj.def_id, |param, _| {
|
||||||
match param.kind {
|
|
||||||
ty::GenericParamDefKind::Type { .. } => {
|
|
||||||
if param.index == 0 {
|
if param.index == 0 {
|
||||||
|
debug_assert_matches!(param.kind, ty::GenericParamDefKind::Type { .. });
|
||||||
return prev_ty.into();
|
return prev_ty.into();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
ty::GenericParamDefKind::Lifetime | ty::GenericParamDefKind::Const { .. } => {}
|
|
||||||
}
|
|
||||||
self.var_for_def(span, param)
|
self.var_for_def(span, param)
|
||||||
});
|
});
|
||||||
// This will hold the resolved type of the associated type, if the
|
// This will hold the resolved type of the associated type, if the
|
||||||
// current expression implements the trait that associated type is
|
// current expression implements the trait that associated type is
|
||||||
// in. For example, this would be what `Iterator::Item` is here.
|
// in. For example, this would be what `Iterator::Item` is here.
|
||||||
let ty_var = self.infcx.next_ty_var(origin);
|
let ty = self.infcx.next_ty_var(origin);
|
||||||
// This corresponds to `<ExprTy as Iterator>::Item = _`.
|
// This corresponds to `<ExprTy as Iterator>::Item = _`.
|
||||||
let projection = ty::Binder::dummy(ty::PredicateKind::Clause(
|
let projection = ty::Binder::dummy(ty::PredicateKind::Clause(
|
||||||
ty::ClauseKind::Projection(ty::ProjectionPredicate {
|
ty::ClauseKind::Projection(ty::ProjectionPredicate {
|
||||||
projection_ty: ty::AliasTy::new(self.tcx, proj.def_id, args),
|
projection_ty: ty::AliasTy::new(self.tcx, proj.def_id, args),
|
||||||
term: ty_var.into(),
|
term: ty.into(),
|
||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
let body_def_id = self.tcx.hir().enclosing_body_owner(body_id);
|
let body_def_id = self.tcx.hir().enclosing_body_owner(body_id);
|
||||||
@ -4254,14 +4250,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
param_env,
|
param_env,
|
||||||
projection,
|
projection,
|
||||||
));
|
));
|
||||||
if ocx.select_where_possible().is_empty() {
|
if ocx.select_where_possible().is_empty()
|
||||||
// `ty_var` now holds the type that `Item` is for `ExprTy`.
|
&& let ty = self.resolve_vars_if_possible(ty)
|
||||||
let ty_var = self.resolve_vars_if_possible(ty_var);
|
&& !ty.is_ty_var()
|
||||||
assocs_in_this_method.push(Some((span, (proj.def_id, ty_var))));
|
{
|
||||||
|
assocs_in_this_method.push(Some((span, (proj.def_id, ty))));
|
||||||
} else {
|
} else {
|
||||||
// `<ExprTy as Iterator>` didn't select, so likely we've
|
// `<ExprTy as Iterator>` didn't select, so likely we've
|
||||||
// reached the end of the iterator chain, like the originating
|
// reached the end of the iterator chain, like the originating
|
||||||
// `Vec<_>`.
|
// `Vec<_>` or the `ty` couldn't be determined.
|
||||||
// Keep the space consistent for later zipping.
|
// Keep the space consistent for later zipping.
|
||||||
assocs_in_this_method.push(None);
|
assocs_in_this_method.push(None);
|
||||||
}
|
}
|
||||||
|
13
tests/ui/macros/defined-later-issue-121061-2.rs
Normal file
13
tests/ui/macros/defined-later-issue-121061-2.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
mod demo {
|
||||||
|
fn hello() {
|
||||||
|
something_later!(); //~ ERROR cannot find macro `something_later` in this scope
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! something_later {
|
||||||
|
() => {
|
||||||
|
println!("successfully expanded!");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
14
tests/ui/macros/defined-later-issue-121061-2.stderr
Normal file
14
tests/ui/macros/defined-later-issue-121061-2.stderr
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
error: cannot find macro `something_later` in this scope
|
||||||
|
--> $DIR/defined-later-issue-121061-2.rs:3:9
|
||||||
|
|
|
||||||
|
LL | something_later!();
|
||||||
|
| ^^^^^^^^^^^^^^^ consider moving the definition of `something_later` before this call
|
||||||
|
|
|
||||||
|
note: a macro with the same name exists, but it appears later at here
|
||||||
|
--> $DIR/defined-later-issue-121061-2.rs:6:18
|
||||||
|
|
|
||||||
|
LL | macro_rules! something_later {
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
9
tests/ui/macros/defined-later-issue-121061.rs
Normal file
9
tests/ui/macros/defined-later-issue-121061.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
fn main() {
|
||||||
|
something_later!(); //~ ERROR cannot find macro `something_later` in this scope
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! something_later {
|
||||||
|
() => {
|
||||||
|
println!("successfully expanded!");
|
||||||
|
};
|
||||||
|
}
|
14
tests/ui/macros/defined-later-issue-121061.stderr
Normal file
14
tests/ui/macros/defined-later-issue-121061.stderr
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
error: cannot find macro `something_later` in this scope
|
||||||
|
--> $DIR/defined-later-issue-121061.rs:2:5
|
||||||
|
|
|
||||||
|
LL | something_later!();
|
||||||
|
| ^^^^^^^^^^^^^^^ consider moving the definition of `something_later` before this call
|
||||||
|
|
|
||||||
|
note: a macro with the same name exists, but it appears later at here
|
||||||
|
--> $DIR/defined-later-issue-121061.rs:5:14
|
||||||
|
|
|
||||||
|
LL | macro_rules! something_later {
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
22
tests/ui/typeck/method-chain-gats.rs
Normal file
22
tests/ui/typeck/method-chain-gats.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Regression test for issue #121898.
|
||||||
|
|
||||||
|
trait Base {
|
||||||
|
type Base<B>;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Functor<A>: Base {
|
||||||
|
fn fmap<B>(self, f: impl Fn(A) -> B) -> Self::Base<B>
|
||||||
|
where
|
||||||
|
Self::Base<B>: Functor<B>;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fmap2<T, A, B, C>(input: T, f1: impl Fn(A) -> B, f2: impl Fn(B) -> C) -> T::Base<C>
|
||||||
|
where
|
||||||
|
T: Functor<A>,
|
||||||
|
T::Base<B>: Functor<B, Base<C> = T::Base<C>>,
|
||||||
|
{
|
||||||
|
input.fmap(f1).fmap(f2)
|
||||||
|
//~^ ERROR the trait bound `<T as Base>::Base<C>: Functor<C>` is not satisfied
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
27
tests/ui/typeck/method-chain-gats.stderr
Normal file
27
tests/ui/typeck/method-chain-gats.stderr
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
error[E0277]: the trait bound `<T as Base>::Base<C>: Functor<C>` is not satisfied
|
||||||
|
--> $DIR/method-chain-gats.rs:18:20
|
||||||
|
|
|
||||||
|
LL | input.fmap(f1).fmap(f2)
|
||||||
|
| ^^^^ the trait `Functor<C>` is not implemented for `<T as Base>::Base<C>`
|
||||||
|
|
|
||||||
|
note: the method call chain might not have had the expected associated types
|
||||||
|
--> $DIR/method-chain-gats.rs:13:29
|
||||||
|
|
|
||||||
|
LL | fn fmap2<T, A, B, C>(input: T, f1: impl Fn(A) -> B, f2: impl Fn(B) -> C) -> T::Base<C>
|
||||||
|
| ^ `Base::Base` is `<T as Base>::Base<_>` here
|
||||||
|
note: required by a bound in `Functor::fmap`
|
||||||
|
--> $DIR/method-chain-gats.rs:10:24
|
||||||
|
|
|
||||||
|
LL | fn fmap<B>(self, f: impl Fn(A) -> B) -> Self::Base<B>
|
||||||
|
| ---- required by a bound in this associated function
|
||||||
|
LL | where
|
||||||
|
LL | Self::Base<B>: Functor<B>;
|
||||||
|
| ^^^^^^^^^^ required by this bound in `Functor::fmap`
|
||||||
|
help: consider further restricting the associated type
|
||||||
|
|
|
||||||
|
LL | T::Base<B>: Functor<B, Base<C> = T::Base<C>>, <T as Base>::Base<C>: Functor<C>
|
||||||
|
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
Loading…
Reference in New Issue
Block a user