mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Auto merge of #104310 - Dylan-DPC:rollup-wgt1z4a, r=Dylan-DPC
Rollup of 7 pull requests Successful merges: - #102049 (Add the `#[derive_const]` attribute) - #103970 (Unhide unknown spans) - #104206 (Remove `save_and_restore_in_snapshot_flag`, use `ObligationCtxt` more) - #104214 (Emit error in `collecting_trait_impl_trait_tys` on mismatched signatures) - #104267 (rustdoc: use checkbox instead of switch for settings toggles) - #104302 (Update cargo) - #104303 (UI tests can be assigned to T-compiler) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
5f4e73c4a4
@ -273,7 +273,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cargo"
|
||||
version = "0.67.0"
|
||||
version = "0.68.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"atty",
|
||||
|
@ -34,6 +34,7 @@ impl MultiItemModifier for Expander {
|
||||
span: Span,
|
||||
meta_item: &ast::MetaItem,
|
||||
item: Annotatable,
|
||||
_is_derive_const: bool,
|
||||
) -> ExpandResult<Vec<Annotatable>, Annotatable> {
|
||||
let template = AttributeTemplate { list: Some("path"), ..Default::default() };
|
||||
let attr = &ecx.attribute(meta_item.clone());
|
||||
|
@ -10,7 +10,7 @@ use rustc_session::Session;
|
||||
use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::Span;
|
||||
|
||||
pub(crate) struct Expander;
|
||||
pub(crate) struct Expander(pub bool);
|
||||
|
||||
impl MultiItemModifier for Expander {
|
||||
fn expand(
|
||||
@ -19,6 +19,7 @@ impl MultiItemModifier for Expander {
|
||||
span: Span,
|
||||
meta_item: &ast::MetaItem,
|
||||
item: Annotatable,
|
||||
_: bool,
|
||||
) -> ExpandResult<Vec<Annotatable>, Annotatable> {
|
||||
let sess = ecx.sess;
|
||||
if report_bad_target(sess, &item, span) {
|
||||
@ -58,20 +59,20 @@ impl MultiItemModifier for Expander {
|
||||
report_path_args(sess, &meta);
|
||||
meta.path
|
||||
})
|
||||
.map(|path| (path, dummy_annotatable(), None))
|
||||
.map(|path| (path, dummy_annotatable(), None, self.0))
|
||||
.collect();
|
||||
|
||||
// Do not configure or clone items unless necessary.
|
||||
match &mut resolutions[..] {
|
||||
[] => {}
|
||||
[(_, first_item, _), others @ ..] => {
|
||||
[(_, first_item, ..), others @ ..] => {
|
||||
*first_item = cfg_eval(
|
||||
sess,
|
||||
features,
|
||||
item.clone(),
|
||||
ecx.current_expansion.lint_node_id,
|
||||
);
|
||||
for (_, item, _) in others {
|
||||
for (_, item, _, _) in others {
|
||||
*item = first_item.clone();
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ pub fn expand_deriving_copy(
|
||||
mitem: &MetaItem,
|
||||
item: &Annotatable,
|
||||
push: &mut dyn FnMut(Annotatable),
|
||||
is_const: bool,
|
||||
) {
|
||||
let trait_def = TraitDef {
|
||||
span,
|
||||
@ -22,6 +23,7 @@ pub fn expand_deriving_copy(
|
||||
supports_unions: true,
|
||||
methods: Vec::new(),
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push);
|
||||
|
@ -14,6 +14,7 @@ pub fn expand_deriving_clone(
|
||||
mitem: &MetaItem,
|
||||
item: &Annotatable,
|
||||
push: &mut dyn FnMut(Annotatable),
|
||||
is_const: bool,
|
||||
) {
|
||||
// The simple form is `fn clone(&self) -> Self { *self }`, possibly with
|
||||
// some additional `AssertParamIsClone` assertions.
|
||||
@ -87,6 +88,7 @@ pub fn expand_deriving_clone(
|
||||
combine_substructure: substructure,
|
||||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
};
|
||||
|
||||
trait_def.expand_ext(cx, mitem, item, push, is_simple)
|
||||
|
@ -15,6 +15,7 @@ pub fn expand_deriving_eq(
|
||||
mitem: &MetaItem,
|
||||
item: &Annotatable,
|
||||
push: &mut dyn FnMut(Annotatable),
|
||||
is_const: bool,
|
||||
) {
|
||||
let span = cx.with_def_site_ctxt(span);
|
||||
let inline = cx.meta_word(span, sym::inline);
|
||||
@ -42,6 +43,7 @@ pub fn expand_deriving_eq(
|
||||
})),
|
||||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
};
|
||||
|
||||
super::inject_impl_of_structural_trait(cx, span, item, path_std!(marker::StructuralEq), push);
|
||||
|
@ -13,6 +13,7 @@ pub fn expand_deriving_ord(
|
||||
mitem: &MetaItem,
|
||||
item: &Annotatable,
|
||||
push: &mut dyn FnMut(Annotatable),
|
||||
is_const: bool,
|
||||
) {
|
||||
let inline = cx.meta_word(span, sym::inline);
|
||||
let attrs = thin_vec![cx.attribute(inline)];
|
||||
@ -34,6 +35,7 @@ pub fn expand_deriving_ord(
|
||||
combine_substructure: combine_substructure(Box::new(|a, b, c| cs_cmp(a, b, c))),
|
||||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
|
@ -14,6 +14,7 @@ pub fn expand_deriving_partial_eq(
|
||||
mitem: &MetaItem,
|
||||
item: &Annotatable,
|
||||
push: &mut dyn FnMut(Annotatable),
|
||||
is_const: bool,
|
||||
) {
|
||||
fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
|
||||
let base = true;
|
||||
@ -89,6 +90,7 @@ pub fn expand_deriving_partial_eq(
|
||||
supports_unions: false,
|
||||
methods,
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
};
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ pub fn expand_deriving_partial_ord(
|
||||
mitem: &MetaItem,
|
||||
item: &Annotatable,
|
||||
push: &mut dyn FnMut(Annotatable),
|
||||
is_const: bool,
|
||||
) {
|
||||
let ordering_ty = Path(path_std!(cmp::Ordering));
|
||||
let ret_ty =
|
||||
@ -43,6 +44,7 @@ pub fn expand_deriving_partial_ord(
|
||||
supports_unions: false,
|
||||
methods: vec![partial_cmp_def],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
};
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ pub fn expand_deriving_debug(
|
||||
mitem: &MetaItem,
|
||||
item: &Annotatable,
|
||||
push: &mut dyn FnMut(Annotatable),
|
||||
is_const: bool,
|
||||
) {
|
||||
// &mut ::std::fmt::Formatter
|
||||
let fmtr = Ref(Box::new(Path(path_std!(fmt::Formatter))), ast::Mutability::Mut);
|
||||
@ -37,6 +38,7 @@ pub fn expand_deriving_debug(
|
||||
})),
|
||||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
};
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ pub fn expand_deriving_rustc_decodable(
|
||||
mitem: &MetaItem,
|
||||
item: &Annotatable,
|
||||
push: &mut dyn FnMut(Annotatable),
|
||||
is_const: bool,
|
||||
) {
|
||||
let krate = sym::rustc_serialize;
|
||||
let typaram = sym::__D;
|
||||
@ -55,6 +56,7 @@ pub fn expand_deriving_rustc_decodable(
|
||||
})),
|
||||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
|
@ -16,6 +16,7 @@ pub fn expand_deriving_default(
|
||||
mitem: &ast::MetaItem,
|
||||
item: &Annotatable,
|
||||
push: &mut dyn FnMut(Annotatable),
|
||||
is_const: bool,
|
||||
) {
|
||||
item.visit_with(&mut DetectNonVariantDefaultAttr { cx });
|
||||
|
||||
@ -47,6 +48,7 @@ pub fn expand_deriving_default(
|
||||
})),
|
||||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
};
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
@ -100,6 +100,7 @@ pub fn expand_deriving_rustc_encodable(
|
||||
mitem: &MetaItem,
|
||||
item: &Annotatable,
|
||||
push: &mut dyn FnMut(Annotatable),
|
||||
is_const: bool,
|
||||
) {
|
||||
let krate = sym::rustc_serialize;
|
||||
let typaram = sym::__S;
|
||||
@ -139,6 +140,7 @@ pub fn expand_deriving_rustc_encodable(
|
||||
})),
|
||||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
|
@ -171,7 +171,7 @@ use rustc_ast::{GenericArg, GenericParamKind, VariantData};
|
||||
use rustc_attr as attr;
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use std::cell::RefCell;
|
||||
use std::iter;
|
||||
use std::ops::Not;
|
||||
@ -204,6 +204,8 @@ pub struct TraitDef<'a> {
|
||||
pub methods: Vec<MethodDef<'a>>,
|
||||
|
||||
pub associated_types: Vec<(Ident, Ty)>,
|
||||
|
||||
pub is_const: bool,
|
||||
}
|
||||
|
||||
pub struct MethodDef<'a> {
|
||||
@ -730,7 +732,7 @@ impl<'a> TraitDef<'a> {
|
||||
unsafety: ast::Unsafe::No,
|
||||
polarity: ast::ImplPolarity::Positive,
|
||||
defaultness: ast::Defaultness::Final,
|
||||
constness: ast::Const::No,
|
||||
constness: if self.is_const { ast::Const::Yes(DUMMY_SP) } else { ast::Const::No },
|
||||
generics: trait_generics,
|
||||
of_trait: opt_trait_ref,
|
||||
self_ty: self_type,
|
||||
|
@ -13,6 +13,7 @@ pub fn expand_deriving_hash(
|
||||
mitem: &MetaItem,
|
||||
item: &Annotatable,
|
||||
push: &mut dyn FnMut(Annotatable),
|
||||
is_const: bool,
|
||||
) {
|
||||
let path = Path::new_(pathvec_std!(hash::Hash), vec![], PathKind::Std);
|
||||
|
||||
@ -39,6 +40,7 @@ pub fn expand_deriving_hash(
|
||||
})),
|
||||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
};
|
||||
|
||||
hash_trait_def.expand(cx, mitem, item, push);
|
||||
|
@ -38,9 +38,10 @@ pub mod partial_ord;
|
||||
|
||||
pub mod generic;
|
||||
|
||||
pub(crate) struct BuiltinDerive(
|
||||
pub(crate) fn(&mut ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable)),
|
||||
);
|
||||
pub(crate) type BuiltinDeriveFn =
|
||||
fn(&mut ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable), bool);
|
||||
|
||||
pub(crate) struct BuiltinDerive(pub(crate) BuiltinDeriveFn);
|
||||
|
||||
impl MultiItemModifier for BuiltinDerive {
|
||||
fn expand(
|
||||
@ -49,6 +50,7 @@ impl MultiItemModifier for BuiltinDerive {
|
||||
span: Span,
|
||||
meta_item: &MetaItem,
|
||||
item: Annotatable,
|
||||
is_derive_const: bool,
|
||||
) -> ExpandResult<Vec<Annotatable>, Annotatable> {
|
||||
// FIXME: Built-in derives often forget to give spans contexts,
|
||||
// so we are doing it here in a centralized way.
|
||||
@ -57,21 +59,28 @@ impl MultiItemModifier for BuiltinDerive {
|
||||
match item {
|
||||
Annotatable::Stmt(stmt) => {
|
||||
if let ast::StmtKind::Item(item) = stmt.into_inner().kind {
|
||||
(self.0)(ecx, span, meta_item, &Annotatable::Item(item), &mut |a| {
|
||||
// Cannot use 'ecx.stmt_item' here, because we need to pass 'ecx'
|
||||
// to the function
|
||||
items.push(Annotatable::Stmt(P(ast::Stmt {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
kind: ast::StmtKind::Item(a.expect_item()),
|
||||
span,
|
||||
})));
|
||||
});
|
||||
(self.0)(
|
||||
ecx,
|
||||
span,
|
||||
meta_item,
|
||||
&Annotatable::Item(item),
|
||||
&mut |a| {
|
||||
// Cannot use 'ecx.stmt_item' here, because we need to pass 'ecx'
|
||||
// to the function
|
||||
items.push(Annotatable::Stmt(P(ast::Stmt {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
kind: ast::StmtKind::Item(a.expect_item()),
|
||||
span,
|
||||
})));
|
||||
},
|
||||
is_derive_const,
|
||||
);
|
||||
} else {
|
||||
unreachable!("should have already errored on non-item statement")
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
(self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a));
|
||||
(self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a), is_derive_const);
|
||||
}
|
||||
}
|
||||
ExpandResult::Ready(items)
|
||||
|
@ -99,7 +99,8 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
|
||||
bench: test::expand_bench,
|
||||
cfg_accessible: cfg_accessible::Expander,
|
||||
cfg_eval: cfg_eval::expand,
|
||||
derive: derive::Expander,
|
||||
derive: derive::Expander(false),
|
||||
derive_const: derive::Expander(true),
|
||||
global_allocator: global_allocator::expand,
|
||||
test: test::expand_test,
|
||||
test_case: test::expand_test_case,
|
||||
|
@ -47,7 +47,10 @@ passes_no_coverage_not_coverable =
|
||||
|
||||
passes_should_be_applied_to_fn =
|
||||
attribute should be applied to a function definition
|
||||
.label = not a function definition
|
||||
.label = {$on_crate ->
|
||||
[true] cannot be applied to crates
|
||||
*[false] not a function definition
|
||||
}
|
||||
|
||||
passes_naked_tracked_caller =
|
||||
cannot use `#[track_caller]` with `#[naked]`
|
||||
|
@ -52,7 +52,6 @@ impl Emitter for AnnotateSnippetEmitterWriter {
|
||||
let (mut primary_span, suggestions) = self.primary_span_formatted(&diag, &fluent_args);
|
||||
|
||||
self.fix_multispans_in_extern_macros_and_render_macro_backtrace(
|
||||
&self.source_map,
|
||||
&mut primary_span,
|
||||
&mut children,
|
||||
&diag.level,
|
||||
|
@ -314,7 +314,6 @@ pub trait Emitter: Translate {
|
||||
|
||||
fn fix_multispans_in_extern_macros_and_render_macro_backtrace(
|
||||
&self,
|
||||
source_map: &Option<Lrc<SourceMap>>,
|
||||
span: &mut MultiSpan,
|
||||
children: &mut Vec<SubDiagnostic>,
|
||||
level: &Level,
|
||||
@ -340,7 +339,7 @@ pub trait Emitter: Translate {
|
||||
.collect();
|
||||
|
||||
if !backtrace {
|
||||
self.fix_multispans_in_extern_macros(source_map, span, children);
|
||||
self.fix_multispans_in_extern_macros(span, children);
|
||||
}
|
||||
|
||||
self.render_multispans_macro_backtrace(span, children, backtrace);
|
||||
@ -480,15 +479,13 @@ pub trait Emitter: Translate {
|
||||
// this will change the span to point at the use site.
|
||||
fn fix_multispans_in_extern_macros(
|
||||
&self,
|
||||
source_map: &Option<Lrc<SourceMap>>,
|
||||
span: &mut MultiSpan,
|
||||
children: &mut Vec<SubDiagnostic>,
|
||||
) {
|
||||
let Some(source_map) = source_map else { return };
|
||||
debug!("fix_multispans_in_extern_macros: before: span={:?} children={:?}", span, children);
|
||||
self.fix_multispan_in_extern_macros(source_map, span);
|
||||
self.fix_multispan_in_extern_macros(span);
|
||||
for child in children.iter_mut() {
|
||||
self.fix_multispan_in_extern_macros(source_map, &mut child.span);
|
||||
self.fix_multispan_in_extern_macros(&mut child.span);
|
||||
}
|
||||
debug!("fix_multispans_in_extern_macros: after: span={:?} children={:?}", span, children);
|
||||
}
|
||||
@ -496,7 +493,8 @@ pub trait Emitter: Translate {
|
||||
// This "fixes" MultiSpans that contain `Span`s pointing to locations inside of external macros.
|
||||
// Since these locations are often difficult to read,
|
||||
// we move these spans from the external macros to their corresponding use site.
|
||||
fn fix_multispan_in_extern_macros(&self, source_map: &Lrc<SourceMap>, span: &mut MultiSpan) {
|
||||
fn fix_multispan_in_extern_macros(&self, span: &mut MultiSpan) {
|
||||
let Some(source_map) = self.source_map() else { return };
|
||||
// First, find all the spans in external macros and point instead at their use site.
|
||||
let replacements: Vec<(Span, Span)> = span
|
||||
.primary_spans()
|
||||
@ -544,7 +542,6 @@ impl Emitter for EmitterWriter {
|
||||
debug!("emit_diagnostic: suggestions={:?}", suggestions);
|
||||
|
||||
self.fix_multispans_in_extern_macros_and_render_macro_backtrace(
|
||||
&self.sm,
|
||||
&mut primary_span,
|
||||
&mut children,
|
||||
&diag.level,
|
||||
@ -2213,22 +2210,45 @@ impl FileWithAnnotatedLines {
|
||||
|
||||
if let Some(ref sm) = emitter.source_map() {
|
||||
for span_label in msp.span_labels() {
|
||||
let fixup_lo_hi = |span: Span| {
|
||||
let lo = sm.lookup_char_pos(span.lo());
|
||||
let mut hi = sm.lookup_char_pos(span.hi());
|
||||
|
||||
// Watch out for "empty spans". If we get a span like 6..6, we
|
||||
// want to just display a `^` at 6, so convert that to
|
||||
// 6..7. This is degenerate input, but it's best to degrade
|
||||
// gracefully -- and the parser likes to supply a span like
|
||||
// that for EOF, in particular.
|
||||
|
||||
if lo.col_display == hi.col_display && lo.line == hi.line {
|
||||
hi.col_display += 1;
|
||||
}
|
||||
(lo, hi)
|
||||
};
|
||||
|
||||
if span_label.span.is_dummy() {
|
||||
if let Some(span) = msp.primary_span() {
|
||||
// if we don't know where to render the annotation, emit it as a note
|
||||
// on the primary span.
|
||||
|
||||
let (lo, hi) = fixup_lo_hi(span);
|
||||
|
||||
let ann = Annotation {
|
||||
start_col: lo.col_display,
|
||||
end_col: hi.col_display,
|
||||
is_primary: span_label.is_primary,
|
||||
label: span_label
|
||||
.label
|
||||
.as_ref()
|
||||
.map(|m| emitter.translate_message(m, args).to_string()),
|
||||
annotation_type: AnnotationType::Singleline,
|
||||
};
|
||||
add_annotation_to_file(&mut output, lo.file, lo.line, ann);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
let lo = sm.lookup_char_pos(span_label.span.lo());
|
||||
let mut hi = sm.lookup_char_pos(span_label.span.hi());
|
||||
|
||||
// Watch out for "empty spans". If we get a span like 6..6, we
|
||||
// want to just display a `^` at 6, so convert that to
|
||||
// 6..7. This is degenerate input, but it's best to degrade
|
||||
// gracefully -- and the parser likes to supply a span like
|
||||
// that for EOF, in particular.
|
||||
|
||||
if lo.col_display == hi.col_display && lo.line == hi.line {
|
||||
hi.col_display += 1;
|
||||
}
|
||||
let (lo, hi) = fixup_lo_hi(span_label.span);
|
||||
|
||||
if lo.line != hi.line {
|
||||
let ml = MultilineAnnotation {
|
||||
|
@ -250,6 +250,7 @@ pub trait MultiItemModifier {
|
||||
span: Span,
|
||||
meta_item: &ast::MetaItem,
|
||||
item: Annotatable,
|
||||
is_derive_const: bool,
|
||||
) -> ExpandResult<Vec<Annotatable>, Annotatable>;
|
||||
}
|
||||
|
||||
@ -263,6 +264,7 @@ where
|
||||
span: Span,
|
||||
meta_item: &ast::MetaItem,
|
||||
item: Annotatable,
|
||||
_is_derive_const: bool,
|
||||
) -> ExpandResult<Vec<Annotatable>, Annotatable> {
|
||||
ExpandResult::Ready(self(ecx, span, meta_item, item))
|
||||
}
|
||||
@ -873,7 +875,7 @@ impl SyntaxExtension {
|
||||
/// Error type that denotes indeterminacy.
|
||||
pub struct Indeterminate;
|
||||
|
||||
pub type DeriveResolutions = Vec<(ast::Path, Annotatable, Option<Lrc<SyntaxExtension>>)>;
|
||||
pub type DeriveResolutions = Vec<(ast::Path, Annotatable, Option<Lrc<SyntaxExtension>>, bool)>;
|
||||
|
||||
pub trait ResolverExpand {
|
||||
fn next_node_id(&mut self) -> NodeId;
|
||||
|
@ -337,6 +337,7 @@ pub enum InvocationKind {
|
||||
},
|
||||
Derive {
|
||||
path: ast::Path,
|
||||
is_const: bool,
|
||||
item: Annotatable,
|
||||
},
|
||||
}
|
||||
@ -478,13 +479,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
derive_invocations.reserve(derives.len());
|
||||
derives
|
||||
.into_iter()
|
||||
.map(|(path, item, _exts)| {
|
||||
.map(|(path, item, _exts, is_const)| {
|
||||
// FIXME: Consider using the derive resolutions (`_exts`)
|
||||
// instead of enqueuing the derives to be resolved again later.
|
||||
let expn_id = LocalExpnId::fresh_empty();
|
||||
derive_invocations.push((
|
||||
Invocation {
|
||||
kind: InvocationKind::Derive { path, item },
|
||||
kind: InvocationKind::Derive { path, item, is_const },
|
||||
fragment_kind,
|
||||
expansion_data: ExpansionData {
|
||||
id: expn_id,
|
||||
@ -717,7 +718,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
SyntaxExtensionKind::LegacyAttr(expander) => {
|
||||
match validate_attr::parse_meta(&self.cx.sess.parse_sess, &attr) {
|
||||
Ok(meta) => {
|
||||
let items = match expander.expand(self.cx, span, &meta, item) {
|
||||
let items = match expander.expand(self.cx, span, &meta, item, false) {
|
||||
ExpandResult::Ready(items) => items,
|
||||
ExpandResult::Retry(item) => {
|
||||
// Reassemble the original invocation for retrying.
|
||||
@ -749,19 +750,19 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
}
|
||||
_ => unreachable!(),
|
||||
},
|
||||
InvocationKind::Derive { path, item } => match ext {
|
||||
InvocationKind::Derive { path, item, is_const } => match ext {
|
||||
SyntaxExtensionKind::Derive(expander)
|
||||
| SyntaxExtensionKind::LegacyDerive(expander) => {
|
||||
if let SyntaxExtensionKind::Derive(..) = ext {
|
||||
self.gate_proc_macro_input(&item);
|
||||
}
|
||||
let meta = ast::MetaItem { kind: MetaItemKind::Word, span, path };
|
||||
let items = match expander.expand(self.cx, span, &meta, item) {
|
||||
let items = match expander.expand(self.cx, span, &meta, item, is_const) {
|
||||
ExpandResult::Ready(items) => items,
|
||||
ExpandResult::Retry(item) => {
|
||||
// Reassemble the original invocation for retrying.
|
||||
return ExpandResult::Retry(Invocation {
|
||||
kind: InvocationKind::Derive { path: meta.path, item },
|
||||
kind: InvocationKind::Derive { path: meta.path, item, is_const },
|
||||
..invoc
|
||||
});
|
||||
}
|
||||
|
@ -112,6 +112,7 @@ impl MultiItemModifier for DeriveProcMacro {
|
||||
span: Span,
|
||||
_meta_item: &ast::MetaItem,
|
||||
item: Annotatable,
|
||||
_is_derive_const: bool,
|
||||
) -> ExpandResult<Vec<Annotatable>, Annotatable> {
|
||||
// We need special handling for statement items
|
||||
// (e.g. `fn foo() { #[derive(Debug)] struct Bar; }`)
|
||||
|
@ -9,14 +9,15 @@ use rustc_hir::intravisit;
|
||||
use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind};
|
||||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::{self, TyCtxtInferExt};
|
||||
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
|
||||
use rustc_infer::traits::util;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::util::ExplicitSelf;
|
||||
use rustc_middle::ty::InternalSubsts;
|
||||
use rustc_middle::ty::{
|
||||
self, AssocItem, DefIdTree, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable,
|
||||
self, AssocItem, DefIdTree, TraitRef, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable,
|
||||
TypeVisitable,
|
||||
};
|
||||
use rustc_middle::ty::{FnSig, InternalSubsts};
|
||||
use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
||||
@ -303,102 +304,19 @@ fn compare_predicate_entailment<'tcx>(
|
||||
}
|
||||
|
||||
if let Err(terr) = result {
|
||||
debug!("sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty);
|
||||
debug!(?terr, "sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty);
|
||||
|
||||
let (impl_err_span, trait_err_span) =
|
||||
extract_spans_for_error_reporting(&infcx, terr, &cause, impl_m, trait_m);
|
||||
|
||||
cause.span = impl_err_span;
|
||||
|
||||
let mut diag = struct_span_err!(
|
||||
tcx.sess,
|
||||
cause.span(),
|
||||
E0053,
|
||||
"method `{}` has an incompatible type for trait",
|
||||
trait_m.name
|
||||
);
|
||||
match &terr {
|
||||
TypeError::ArgumentMutability(0) | TypeError::ArgumentSorts(_, 0)
|
||||
if trait_m.fn_has_self_parameter =>
|
||||
{
|
||||
let ty = trait_sig.inputs()[0];
|
||||
let sugg = match ExplicitSelf::determine(ty, |_| ty == impl_trait_ref.self_ty()) {
|
||||
ExplicitSelf::ByValue => "self".to_owned(),
|
||||
ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(),
|
||||
ExplicitSelf::ByReference(_, hir::Mutability::Mut) => "&mut self".to_owned(),
|
||||
_ => format!("self: {ty}"),
|
||||
};
|
||||
|
||||
// When the `impl` receiver is an arbitrary self type, like `self: Box<Self>`, the
|
||||
// span points only at the type `Box<Self`>, but we want to cover the whole
|
||||
// argument pattern and type.
|
||||
let span = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
|
||||
ImplItemKind::Fn(ref sig, body) => tcx
|
||||
.hir()
|
||||
.body_param_names(body)
|
||||
.zip(sig.decl.inputs.iter())
|
||||
.map(|(param, ty)| param.span.to(ty.span))
|
||||
.next()
|
||||
.unwrap_or(impl_err_span),
|
||||
_ => bug!("{:?} is not a method", impl_m),
|
||||
};
|
||||
|
||||
diag.span_suggestion(
|
||||
span,
|
||||
"change the self-receiver type to match the trait",
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(_, i) => {
|
||||
if trait_sig.inputs().len() == *i {
|
||||
// Suggestion to change output type. We do not suggest in `async` functions
|
||||
// to avoid complex logic or incorrect output.
|
||||
match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
|
||||
ImplItemKind::Fn(ref sig, _)
|
||||
if sig.header.asyncness == hir::IsAsync::NotAsync =>
|
||||
{
|
||||
let msg = "change the output type to match the trait";
|
||||
let ap = Applicability::MachineApplicable;
|
||||
match sig.decl.output {
|
||||
hir::FnRetTy::DefaultReturn(sp) => {
|
||||
let sugg = format!("-> {} ", trait_sig.output());
|
||||
diag.span_suggestion_verbose(sp, msg, sugg, ap);
|
||||
}
|
||||
hir::FnRetTy::Return(hir_ty) => {
|
||||
let sugg = trait_sig.output();
|
||||
diag.span_suggestion(hir_ty.span, msg, sugg, ap);
|
||||
}
|
||||
};
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
} else if let Some(trait_ty) = trait_sig.inputs().get(*i) {
|
||||
diag.span_suggestion(
|
||||
impl_err_span,
|
||||
"change the parameter type to match the trait",
|
||||
trait_ty,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
infcx.err_ctxt().note_type_err(
|
||||
&mut diag,
|
||||
&cause,
|
||||
trait_err_span.map(|sp| (sp, "type in trait".to_owned())),
|
||||
Some(infer::ValuePairs::Terms(ExpectedFound {
|
||||
expected: trait_fty.into(),
|
||||
found: impl_fty.into(),
|
||||
})),
|
||||
let emitted = report_trait_method_mismatch(
|
||||
tcx,
|
||||
&mut cause,
|
||||
&infcx,
|
||||
terr,
|
||||
false,
|
||||
false,
|
||||
(trait_m, trait_fty),
|
||||
(impl_m, impl_fty),
|
||||
&trait_sig,
|
||||
&impl_trait_ref,
|
||||
);
|
||||
|
||||
return Err(diag.emit());
|
||||
return Err(emitted);
|
||||
}
|
||||
|
||||
// Check that all obligations are satisfied by the implementation's
|
||||
@ -424,6 +342,7 @@ fn compare_predicate_entailment<'tcx>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument(skip(tcx), level = "debug", ret)]
|
||||
pub fn collect_trait_impl_trait_tys<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
@ -437,7 +356,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
|
||||
|
||||
let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
|
||||
let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span();
|
||||
let cause = ObligationCause::new(
|
||||
let mut cause = ObligationCause::new(
|
||||
return_span,
|
||||
impl_m_hir_id,
|
||||
ObligationCauseCode::CompareImplItemObligation {
|
||||
@ -514,23 +433,35 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
debug!(?trait_sig, ?impl_sig, "equating function signatures");
|
||||
|
||||
let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig));
|
||||
let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig));
|
||||
|
||||
// Unify the whole function signature. We need to do this to fully infer
|
||||
// the lifetimes of the return type, but do this after unifying just the
|
||||
// return types, since we want to avoid duplicating errors from
|
||||
// `compare_predicate_entailment`.
|
||||
match infcx
|
||||
.at(&cause, param_env)
|
||||
.eq(tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig)), tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig)))
|
||||
{
|
||||
match infcx.at(&cause, param_env).eq(trait_fty, impl_fty) {
|
||||
Ok(infer::InferOk { value: (), obligations }) => {
|
||||
ocx.register_obligations(obligations);
|
||||
}
|
||||
Err(terr) => {
|
||||
let guar = tcx.sess.delay_span_bug(
|
||||
return_span,
|
||||
format!("could not unify `{trait_sig}` and `{impl_sig}`: {terr:?}"),
|
||||
// This function gets called during `compare_predicate_entailment` when normalizing a
|
||||
// signature that contains RPITIT. When the method signatures don't match, we have to
|
||||
// emit an error now because `compare_predicate_entailment` will not report the error
|
||||
// when normalization fails.
|
||||
let emitted = report_trait_method_mismatch(
|
||||
tcx,
|
||||
&mut cause,
|
||||
infcx,
|
||||
terr,
|
||||
(trait_m, trait_fty),
|
||||
(impl_m, impl_fty),
|
||||
&trait_sig,
|
||||
&impl_trait_ref,
|
||||
);
|
||||
return Err(guar);
|
||||
return Err(emitted);
|
||||
}
|
||||
}
|
||||
|
||||
@ -690,6 +621,112 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn report_trait_method_mismatch<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
cause: &mut ObligationCause<'tcx>,
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
terr: TypeError<'tcx>,
|
||||
(trait_m, trait_fty): (&AssocItem, Ty<'tcx>),
|
||||
(impl_m, impl_fty): (&AssocItem, Ty<'tcx>),
|
||||
trait_sig: &FnSig<'tcx>,
|
||||
impl_trait_ref: &TraitRef<'tcx>,
|
||||
) -> ErrorGuaranteed {
|
||||
let (impl_err_span, trait_err_span) =
|
||||
extract_spans_for_error_reporting(&infcx, terr, &cause, impl_m, trait_m);
|
||||
|
||||
cause.span = impl_err_span;
|
||||
|
||||
let mut diag = struct_span_err!(
|
||||
tcx.sess,
|
||||
cause.span(),
|
||||
E0053,
|
||||
"method `{}` has an incompatible type for trait",
|
||||
trait_m.name
|
||||
);
|
||||
match &terr {
|
||||
TypeError::ArgumentMutability(0) | TypeError::ArgumentSorts(_, 0)
|
||||
if trait_m.fn_has_self_parameter =>
|
||||
{
|
||||
let ty = trait_sig.inputs()[0];
|
||||
let sugg = match ExplicitSelf::determine(ty, |_| ty == impl_trait_ref.self_ty()) {
|
||||
ExplicitSelf::ByValue => "self".to_owned(),
|
||||
ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(),
|
||||
ExplicitSelf::ByReference(_, hir::Mutability::Mut) => "&mut self".to_owned(),
|
||||
_ => format!("self: {ty}"),
|
||||
};
|
||||
|
||||
// When the `impl` receiver is an arbitrary self type, like `self: Box<Self>`, the
|
||||
// span points only at the type `Box<Self`>, but we want to cover the whole
|
||||
// argument pattern and type.
|
||||
let span = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
|
||||
ImplItemKind::Fn(ref sig, body) => tcx
|
||||
.hir()
|
||||
.body_param_names(body)
|
||||
.zip(sig.decl.inputs.iter())
|
||||
.map(|(param, ty)| param.span.to(ty.span))
|
||||
.next()
|
||||
.unwrap_or(impl_err_span),
|
||||
_ => bug!("{:?} is not a method", impl_m),
|
||||
};
|
||||
|
||||
diag.span_suggestion(
|
||||
span,
|
||||
"change the self-receiver type to match the trait",
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(_, i) => {
|
||||
if trait_sig.inputs().len() == *i {
|
||||
// Suggestion to change output type. We do not suggest in `async` functions
|
||||
// to avoid complex logic or incorrect output.
|
||||
match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
|
||||
ImplItemKind::Fn(ref sig, _)
|
||||
if sig.header.asyncness == hir::IsAsync::NotAsync =>
|
||||
{
|
||||
let msg = "change the output type to match the trait";
|
||||
let ap = Applicability::MachineApplicable;
|
||||
match sig.decl.output {
|
||||
hir::FnRetTy::DefaultReturn(sp) => {
|
||||
let sugg = format!("-> {} ", trait_sig.output());
|
||||
diag.span_suggestion_verbose(sp, msg, sugg, ap);
|
||||
}
|
||||
hir::FnRetTy::Return(hir_ty) => {
|
||||
let sugg = trait_sig.output();
|
||||
diag.span_suggestion(hir_ty.span, msg, sugg, ap);
|
||||
}
|
||||
};
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
} else if let Some(trait_ty) = trait_sig.inputs().get(*i) {
|
||||
diag.span_suggestion(
|
||||
impl_err_span,
|
||||
"change the parameter type to match the trait",
|
||||
trait_ty,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
infcx.err_ctxt().note_type_err(
|
||||
&mut diag,
|
||||
&cause,
|
||||
trait_err_span.map(|sp| (sp, "type in trait".to_owned())),
|
||||
Some(infer::ValuePairs::Terms(ExpectedFound {
|
||||
expected: trait_fty.into(),
|
||||
found: impl_fty.into(),
|
||||
})),
|
||||
terr,
|
||||
false,
|
||||
false,
|
||||
);
|
||||
|
||||
return diag.emit();
|
||||
}
|
||||
|
||||
fn check_region_bounds_on_impl_item<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
impl_m: &ty::AssocItem,
|
||||
|
@ -18,6 +18,7 @@ use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryRespons
|
||||
use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
|
||||
use rustc_infer::infer::{InferOk, InferResult};
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::fold::TypeFoldable;
|
||||
use rustc_middle::ty::visit::TypeVisitable;
|
||||
use rustc_middle::ty::{
|
||||
@ -32,9 +33,7 @@ use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_trait_selection::infer::InferCtxtExt as _;
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
|
||||
use rustc_trait_selection::traits::{
|
||||
self, ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt,
|
||||
};
|
||||
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, ObligationCtxt};
|
||||
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::slice;
|
||||
@ -766,34 +765,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
let expect_args = self
|
||||
.fudge_inference_if_ok(|| {
|
||||
let ocx = ObligationCtxt::new_in_snapshot(self);
|
||||
|
||||
// Attempt to apply a subtyping relationship between the formal
|
||||
// return type (likely containing type variables if the function
|
||||
// is polymorphic) and the expected return type.
|
||||
// No argument expectations are produced if unification fails.
|
||||
let origin = self.misc(call_span);
|
||||
let ures = self.at(&origin, self.param_env).sup(ret_ty, formal_ret);
|
||||
|
||||
// FIXME(#27336) can't use ? here, Try::from_error doesn't default
|
||||
// to identity so the resulting type is not constrained.
|
||||
match ures {
|
||||
Ok(ok) => {
|
||||
// Process any obligations locally as much as
|
||||
// we can. We don't care if some things turn
|
||||
// out unconstrained or ambiguous, as we're
|
||||
// just trying to get hints here.
|
||||
let errors = self.save_and_restore_in_snapshot_flag(|_| {
|
||||
let mut fulfill = <dyn TraitEngine<'_>>::new(self.tcx);
|
||||
for obligation in ok.obligations {
|
||||
fulfill.register_predicate_obligation(self, obligation);
|
||||
}
|
||||
fulfill.select_where_possible(self)
|
||||
});
|
||||
|
||||
if !errors.is_empty() {
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
Err(_) => return Err(()),
|
||||
ocx.sup(&origin, self.param_env, ret_ty, formal_ret)?;
|
||||
if !ocx.select_where_possible().is_empty() {
|
||||
return Err(TypeError::Mismatch);
|
||||
}
|
||||
|
||||
// Record all the argument types, with the substitutions
|
||||
|
@ -778,32 +778,6 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Clear the "currently in a snapshot" flag, invoke the closure,
|
||||
/// then restore the flag to its original value. This flag is a
|
||||
/// debugging measure designed to detect cases where we start a
|
||||
/// snapshot, create type variables, and register obligations
|
||||
/// which may involve those type variables in the fulfillment cx,
|
||||
/// potentially leaving "dangling type variables" behind.
|
||||
/// In such cases, an assertion will fail when attempting to
|
||||
/// register obligations, within a snapshot. Very useful, much
|
||||
/// better than grovelling through megabytes of `RUSTC_LOG` output.
|
||||
///
|
||||
/// HOWEVER, in some cases the flag is unhelpful. In particular, we
|
||||
/// sometimes create a "mini-fulfilment-cx" in which we enroll
|
||||
/// obligations. As long as this fulfillment cx is fully drained
|
||||
/// before we return, this is not a problem, as there won't be any
|
||||
/// escaping obligations in the main cx. In those cases, you can
|
||||
/// use this function.
|
||||
pub fn save_and_restore_in_snapshot_flag<F, R>(&self, func: F) -> R
|
||||
where
|
||||
F: FnOnce(&Self) -> R,
|
||||
{
|
||||
let flag = self.in_snapshot.replace(false);
|
||||
let result = func(self);
|
||||
self.in_snapshot.set(flag);
|
||||
result
|
||||
}
|
||||
|
||||
fn start_snapshot(&self) -> CombinedSnapshot<'tcx> {
|
||||
debug!("start_snapshot()");
|
||||
|
||||
|
@ -119,13 +119,13 @@ impl CheckAttrVisitor<'_> {
|
||||
}
|
||||
sym::naked => self.check_naked(hir_id, attr, span, target),
|
||||
sym::rustc_legacy_const_generics => {
|
||||
self.check_rustc_legacy_const_generics(&attr, span, target, item)
|
||||
self.check_rustc_legacy_const_generics(hir_id, &attr, span, target, item)
|
||||
}
|
||||
sym::rustc_lint_query_instability => {
|
||||
self.check_rustc_lint_query_instability(&attr, span, target)
|
||||
self.check_rustc_lint_query_instability(hir_id, &attr, span, target)
|
||||
}
|
||||
sym::rustc_lint_diagnostics => {
|
||||
self.check_rustc_lint_diagnostics(&attr, span, target)
|
||||
self.check_rustc_lint_diagnostics(hir_id, &attr, span, target)
|
||||
}
|
||||
sym::rustc_lint_opt_ty => self.check_rustc_lint_opt_ty(&attr, span, target),
|
||||
sym::rustc_lint_opt_deny_field_access => {
|
||||
@ -135,7 +135,9 @@ impl CheckAttrVisitor<'_> {
|
||||
| sym::rustc_dirty
|
||||
| sym::rustc_if_this_changed
|
||||
| sym::rustc_then_this_would_need => self.check_rustc_dirty_clean(&attr),
|
||||
sym::cmse_nonsecure_entry => self.check_cmse_nonsecure_entry(attr, span, target),
|
||||
sym::cmse_nonsecure_entry => {
|
||||
self.check_cmse_nonsecure_entry(hir_id, attr, span, target)
|
||||
}
|
||||
sym::collapse_debuginfo => self.check_collapse_debuginfo(attr, span, target),
|
||||
sym::const_trait => self.check_const_trait(attr, span, target),
|
||||
sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target),
|
||||
@ -386,6 +388,7 @@ impl CheckAttrVisitor<'_> {
|
||||
self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn {
|
||||
attr_span: attr.span,
|
||||
defn_span: span,
|
||||
on_crate: hir_id == CRATE_HIR_ID,
|
||||
});
|
||||
false
|
||||
}
|
||||
@ -393,7 +396,13 @@ impl CheckAttrVisitor<'_> {
|
||||
}
|
||||
|
||||
/// Checks if `#[cmse_nonsecure_entry]` is applied to a function definition.
|
||||
fn check_cmse_nonsecure_entry(&self, attr: &Attribute, span: Span, target: Target) -> bool {
|
||||
fn check_cmse_nonsecure_entry(
|
||||
&self,
|
||||
hir_id: HirId,
|
||||
attr: &Attribute,
|
||||
span: Span,
|
||||
target: Target,
|
||||
) -> bool {
|
||||
match target {
|
||||
Target::Fn
|
||||
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
|
||||
@ -401,6 +410,7 @@ impl CheckAttrVisitor<'_> {
|
||||
self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn {
|
||||
attr_span: attr.span,
|
||||
defn_span: span,
|
||||
on_crate: hir_id == CRATE_HIR_ID,
|
||||
});
|
||||
false
|
||||
}
|
||||
@ -465,9 +475,11 @@ impl CheckAttrVisitor<'_> {
|
||||
true
|
||||
}
|
||||
_ => {
|
||||
self.tcx
|
||||
.sess
|
||||
.emit_err(errors::TrackedCallerWrongLocation { attr_span, defn_span: span });
|
||||
self.tcx.sess.emit_err(errors::TrackedCallerWrongLocation {
|
||||
attr_span,
|
||||
defn_span: span,
|
||||
on_crate: hir_id == CRATE_HIR_ID,
|
||||
});
|
||||
false
|
||||
}
|
||||
}
|
||||
@ -576,6 +588,7 @@ impl CheckAttrVisitor<'_> {
|
||||
self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn {
|
||||
attr_span: attr.span,
|
||||
defn_span: span,
|
||||
on_crate: hir_id == CRATE_HIR_ID,
|
||||
});
|
||||
false
|
||||
}
|
||||
@ -1230,7 +1243,7 @@ impl CheckAttrVisitor<'_> {
|
||||
UNUSED_ATTRIBUTES,
|
||||
hir_id,
|
||||
attr.span,
|
||||
errors::Cold { span },
|
||||
errors::Cold { span, on_crate: hir_id == CRATE_HIR_ID },
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1366,6 +1379,7 @@ impl CheckAttrVisitor<'_> {
|
||||
/// Checks if `#[rustc_legacy_const_generics]` is applied to a function and has a valid argument.
|
||||
fn check_rustc_legacy_const_generics(
|
||||
&self,
|
||||
hir_id: HirId,
|
||||
attr: &Attribute,
|
||||
span: Span,
|
||||
target: Target,
|
||||
@ -1376,6 +1390,7 @@ impl CheckAttrVisitor<'_> {
|
||||
self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn {
|
||||
attr_span: attr.span,
|
||||
defn_span: span,
|
||||
on_crate: hir_id == CRATE_HIR_ID,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
@ -1440,12 +1455,19 @@ impl CheckAttrVisitor<'_> {
|
||||
|
||||
/// Helper function for checking that the provided attribute is only applied to a function or
|
||||
/// method.
|
||||
fn check_applied_to_fn_or_method(&self, attr: &Attribute, span: Span, target: Target) -> bool {
|
||||
fn check_applied_to_fn_or_method(
|
||||
&self,
|
||||
hir_id: HirId,
|
||||
attr: &Attribute,
|
||||
span: Span,
|
||||
target: Target,
|
||||
) -> bool {
|
||||
let is_function = matches!(target, Target::Fn | Target::Method(..));
|
||||
if !is_function {
|
||||
self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn {
|
||||
attr_span: attr.span,
|
||||
defn_span: span,
|
||||
on_crate: hir_id == CRATE_HIR_ID,
|
||||
});
|
||||
false
|
||||
} else {
|
||||
@ -1457,17 +1479,24 @@ impl CheckAttrVisitor<'_> {
|
||||
/// or method.
|
||||
fn check_rustc_lint_query_instability(
|
||||
&self,
|
||||
hir_id: HirId,
|
||||
attr: &Attribute,
|
||||
span: Span,
|
||||
target: Target,
|
||||
) -> bool {
|
||||
self.check_applied_to_fn_or_method(attr, span, target)
|
||||
self.check_applied_to_fn_or_method(hir_id, attr, span, target)
|
||||
}
|
||||
|
||||
/// Checks that the `#[rustc_lint_diagnostics]` attribute is only applied to a function or
|
||||
/// method.
|
||||
fn check_rustc_lint_diagnostics(&self, attr: &Attribute, span: Span, target: Target) -> bool {
|
||||
self.check_applied_to_fn_or_method(attr, span, target)
|
||||
fn check_rustc_lint_diagnostics(
|
||||
&self,
|
||||
hir_id: HirId,
|
||||
attr: &Attribute,
|
||||
span: Span,
|
||||
target: Target,
|
||||
) -> bool {
|
||||
self.check_applied_to_fn_or_method(hir_id, attr, span, target)
|
||||
}
|
||||
|
||||
/// Checks that the `#[rustc_lint_opt_ty]` attribute is only applied to a struct.
|
||||
|
@ -81,6 +81,7 @@ pub struct AttrShouldBeAppliedToFn {
|
||||
pub attr_span: Span,
|
||||
#[label]
|
||||
pub defn_span: Span,
|
||||
pub on_crate: bool,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -97,6 +98,7 @@ pub struct TrackedCallerWrongLocation {
|
||||
pub attr_span: Span,
|
||||
#[label]
|
||||
pub defn_span: Span,
|
||||
pub on_crate: bool,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -367,6 +369,7 @@ pub struct MustNotSuspend {
|
||||
pub struct Cold {
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub on_crate: bool,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
|
@ -241,10 +241,12 @@ impl<'a> Resolver<'a> {
|
||||
));
|
||||
|
||||
err.span_label(span, format!("`{}` re{} here", name, new_participle));
|
||||
err.span_label(
|
||||
self.session.source_map().guess_head_span(old_binding.span),
|
||||
format!("previous {} of the {} `{}` here", old_noun, old_kind, name),
|
||||
);
|
||||
if !old_binding.span.is_dummy() && old_binding.span != span {
|
||||
err.span_label(
|
||||
self.session.source_map().guess_head_span(old_binding.span),
|
||||
format!("previous {} of the {} `{}` here", old_noun, old_kind, name),
|
||||
);
|
||||
}
|
||||
|
||||
// See https://github.com/rust-lang/rust/issues/32354
|
||||
use NameBindingKind::Import;
|
||||
|
@ -807,14 +807,16 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
|
||||
err.code(rustc_errors::error_code!(E0411));
|
||||
err.span_label(span, "`Self` is only available in impls, traits, and type definitions");
|
||||
if let Some(item_kind) = self.diagnostic_metadata.current_item {
|
||||
err.span_label(
|
||||
item_kind.ident.span,
|
||||
format!(
|
||||
"`Self` not allowed in {} {}",
|
||||
item_kind.kind.article(),
|
||||
item_kind.kind.descr()
|
||||
),
|
||||
);
|
||||
if !item_kind.ident.span.is_dummy() {
|
||||
err.span_label(
|
||||
item_kind.ident.span,
|
||||
format!(
|
||||
"`Self` not allowed in {} {}",
|
||||
item_kind.kind.article(),
|
||||
item_kind.kind.descr()
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
@ -356,7 +356,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
|
||||
has_derive_copy: false,
|
||||
});
|
||||
let parent_scope = self.invocation_parent_scopes[&expn_id];
|
||||
for (i, (path, _, opt_ext)) in entry.resolutions.iter_mut().enumerate() {
|
||||
for (i, (path, _, opt_ext, _)) in entry.resolutions.iter_mut().enumerate() {
|
||||
if opt_ext.is_none() {
|
||||
*opt_ext = Some(
|
||||
match self.resolve_macro_path(
|
||||
|
@ -620,6 +620,7 @@ symbols! {
|
||||
deref_mut,
|
||||
deref_target,
|
||||
derive,
|
||||
derive_const,
|
||||
derive_default_enum,
|
||||
destruct,
|
||||
destructuring_assignment,
|
||||
|
@ -2445,12 +2445,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
(Ok(l), Ok(r)) => l.line == r.line,
|
||||
_ => true,
|
||||
};
|
||||
if !ident.span.overlaps(span) && !same_line {
|
||||
if !ident.span.is_dummy() && !ident.span.overlaps(span) && !same_line {
|
||||
multispan.push_span_label(ident.span, "required by a bound in this");
|
||||
}
|
||||
}
|
||||
let descr = format!("required by a bound in `{}`", item_name);
|
||||
if span != DUMMY_SP {
|
||||
if !span.is_dummy() {
|
||||
let msg = format!("required by this bound in `{}`", item_name);
|
||||
multispan.push_span_label(span, msg);
|
||||
err.span_note(multispan, &descr);
|
||||
|
@ -10,10 +10,12 @@
|
||||
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/specialization.html
|
||||
|
||||
pub mod specialization_graph;
|
||||
use rustc_infer::traits::{TraitEngine, TraitEngineExt as _};
|
||||
use specialization_graph::GraphExt;
|
||||
|
||||
use crate::errors::NegativePositiveConflict;
|
||||
use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt};
|
||||
use crate::traits::engine::TraitEngineExt as _;
|
||||
use crate::traits::select::IntercrateAmbiguityCause;
|
||||
use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause};
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
@ -200,36 +202,32 @@ fn fulfill_implication<'tcx>(
|
||||
return Err(());
|
||||
};
|
||||
|
||||
// Needs to be `in_snapshot` because this function is used to rebase
|
||||
// substitutions, which may happen inside of a select within a probe.
|
||||
let mut engine = <dyn TraitEngine<'tcx>>::new_in_snapshot(infcx.tcx);
|
||||
// attempt to prove all of the predicates for impl2 given those for impl1
|
||||
// (which are packed up in penv)
|
||||
engine.register_predicate_obligations(infcx, obligations.chain(more_obligations));
|
||||
|
||||
infcx.save_and_restore_in_snapshot_flag(|infcx| {
|
||||
let errors = traits::fully_solve_obligations(&infcx, obligations.chain(more_obligations));
|
||||
match &errors[..] {
|
||||
[] => {
|
||||
debug!(
|
||||
"fulfill_implication: an impl for {:?} specializes {:?}",
|
||||
source_trait, target_trait
|
||||
);
|
||||
let errors = engine.select_all_or_error(infcx);
|
||||
if !errors.is_empty() {
|
||||
// no dice!
|
||||
debug!(
|
||||
"fulfill_implication: for impls on {:?} and {:?}, \
|
||||
could not fulfill: {:?} given {:?}",
|
||||
source_trait,
|
||||
target_trait,
|
||||
errors,
|
||||
param_env.caller_bounds()
|
||||
);
|
||||
return Err(());
|
||||
}
|
||||
|
||||
// Now resolve the *substitution* we built for the target earlier, replacing
|
||||
// the inference variables inside with whatever we got from fulfillment.
|
||||
Ok(infcx.resolve_vars_if_possible(target_substs))
|
||||
}
|
||||
errors => {
|
||||
// no dice!
|
||||
debug!(
|
||||
"fulfill_implication: for impls on {:?} and {:?}, \
|
||||
could not fulfill: {:?} given {:?}",
|
||||
source_trait,
|
||||
target_trait,
|
||||
errors,
|
||||
param_env.caller_bounds()
|
||||
);
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
})
|
||||
debug!("fulfill_implication: an impl for {:?} specializes {:?}", source_trait, target_trait);
|
||||
|
||||
// Now resolve the *substitution* we built for the target earlier, replacing
|
||||
// the inference variables inside with whatever we got from fulfillment.
|
||||
Ok(infcx.resolve_vars_if_possible(target_substs))
|
||||
}
|
||||
|
||||
// Query provider for `specialization_graph_of`.
|
||||
|
@ -2,20 +2,18 @@ use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_infer::infer::canonical::{Canonical, QueryResponse};
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_infer::traits::TraitEngineExt as _;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::InternalSubsts;
|
||||
use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, Ty, TyCtxt};
|
||||
use rustc_span::source_map::{Span, DUMMY_SP};
|
||||
use rustc_trait_selection::infer::InferCtxtBuilderExt;
|
||||
use rustc_trait_selection::traits::query::dropck_outlives::trivial_dropck_outlives;
|
||||
use rustc_trait_selection::traits::query::dropck_outlives::{
|
||||
DropckConstraint, DropckOutlivesResult,
|
||||
};
|
||||
use rustc_trait_selection::traits::query::normalize::AtExt;
|
||||
use rustc_trait_selection::traits::query::{CanonicalTyGoal, NoSolution};
|
||||
use rustc_trait_selection::traits::{
|
||||
Normalized, ObligationCause, TraitEngine, TraitEngineExt as _,
|
||||
};
|
||||
use rustc_trait_selection::traits::{Normalized, ObligationCause};
|
||||
|
||||
pub(crate) fn provide(p: &mut Providers) {
|
||||
*p = Providers { dropck_outlives, adt_dtorck_constraint, ..*p };
|
||||
@ -27,120 +25,109 @@ fn dropck_outlives<'tcx>(
|
||||
) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, DropckOutlivesResult<'tcx>>>, NoSolution> {
|
||||
debug!("dropck_outlives(goal={:#?})", canonical_goal);
|
||||
|
||||
let (ref infcx, goal, canonical_inference_vars) =
|
||||
tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &canonical_goal);
|
||||
let tcx = infcx.tcx;
|
||||
let ParamEnvAnd { param_env, value: for_ty } = goal;
|
||||
tcx.infer_ctxt().enter_canonical_trait_query(&canonical_goal, |ocx, goal| {
|
||||
let tcx = ocx.infcx.tcx;
|
||||
let ParamEnvAnd { param_env, value: for_ty } = goal;
|
||||
|
||||
let mut result = DropckOutlivesResult { kinds: vec![], overflows: vec![] };
|
||||
let mut result = DropckOutlivesResult { kinds: vec![], overflows: vec![] };
|
||||
|
||||
// A stack of types left to process. Each round, we pop
|
||||
// something from the stack and invoke
|
||||
// `dtorck_constraint_for_ty`. This may produce new types that
|
||||
// have to be pushed on the stack. This continues until we have explored
|
||||
// all the reachable types from the type `for_ty`.
|
||||
//
|
||||
// Example: Imagine that we have the following code:
|
||||
//
|
||||
// ```rust
|
||||
// struct A {
|
||||
// value: B,
|
||||
// children: Vec<A>,
|
||||
// }
|
||||
//
|
||||
// struct B {
|
||||
// value: u32
|
||||
// }
|
||||
//
|
||||
// fn f() {
|
||||
// let a: A = ...;
|
||||
// ..
|
||||
// } // here, `a` is dropped
|
||||
// ```
|
||||
//
|
||||
// at the point where `a` is dropped, we need to figure out
|
||||
// which types inside of `a` contain region data that may be
|
||||
// accessed by any destructors in `a`. We begin by pushing `A`
|
||||
// onto the stack, as that is the type of `a`. We will then
|
||||
// invoke `dtorck_constraint_for_ty` which will expand `A`
|
||||
// into the types of its fields `(B, Vec<A>)`. These will get
|
||||
// pushed onto the stack. Eventually, expanding `Vec<A>` will
|
||||
// lead to us trying to push `A` a second time -- to prevent
|
||||
// infinite recursion, we notice that `A` was already pushed
|
||||
// once and stop.
|
||||
let mut ty_stack = vec![(for_ty, 0)];
|
||||
// A stack of types left to process. Each round, we pop
|
||||
// something from the stack and invoke
|
||||
// `dtorck_constraint_for_ty`. This may produce new types that
|
||||
// have to be pushed on the stack. This continues until we have explored
|
||||
// all the reachable types from the type `for_ty`.
|
||||
//
|
||||
// Example: Imagine that we have the following code:
|
||||
//
|
||||
// ```rust
|
||||
// struct A {
|
||||
// value: B,
|
||||
// children: Vec<A>,
|
||||
// }
|
||||
//
|
||||
// struct B {
|
||||
// value: u32
|
||||
// }
|
||||
//
|
||||
// fn f() {
|
||||
// let a: A = ...;
|
||||
// ..
|
||||
// } // here, `a` is dropped
|
||||
// ```
|
||||
//
|
||||
// at the point where `a` is dropped, we need to figure out
|
||||
// which types inside of `a` contain region data that may be
|
||||
// accessed by any destructors in `a`. We begin by pushing `A`
|
||||
// onto the stack, as that is the type of `a`. We will then
|
||||
// invoke `dtorck_constraint_for_ty` which will expand `A`
|
||||
// into the types of its fields `(B, Vec<A>)`. These will get
|
||||
// pushed onto the stack. Eventually, expanding `Vec<A>` will
|
||||
// lead to us trying to push `A` a second time -- to prevent
|
||||
// infinite recursion, we notice that `A` was already pushed
|
||||
// once and stop.
|
||||
let mut ty_stack = vec![(for_ty, 0)];
|
||||
|
||||
// Set used to detect infinite recursion.
|
||||
let mut ty_set = FxHashSet::default();
|
||||
// Set used to detect infinite recursion.
|
||||
let mut ty_set = FxHashSet::default();
|
||||
|
||||
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
|
||||
let cause = ObligationCause::dummy();
|
||||
let mut constraints = DropckConstraint::empty();
|
||||
while let Some((ty, depth)) = ty_stack.pop() {
|
||||
debug!(
|
||||
"{} kinds, {} overflows, {} ty_stack",
|
||||
result.kinds.len(),
|
||||
result.overflows.len(),
|
||||
ty_stack.len()
|
||||
);
|
||||
dtorck_constraint_for_ty(tcx, DUMMY_SP, for_ty, depth, ty, &mut constraints)?;
|
||||
|
||||
let cause = ObligationCause::dummy();
|
||||
let mut constraints = DropckConstraint::empty();
|
||||
while let Some((ty, depth)) = ty_stack.pop() {
|
||||
debug!(
|
||||
"{} kinds, {} overflows, {} ty_stack",
|
||||
result.kinds.len(),
|
||||
result.overflows.len(),
|
||||
ty_stack.len()
|
||||
);
|
||||
dtorck_constraint_for_ty(tcx, DUMMY_SP, for_ty, depth, ty, &mut constraints)?;
|
||||
// "outlives" represent types/regions that may be touched
|
||||
// by a destructor.
|
||||
result.kinds.append(&mut constraints.outlives);
|
||||
result.overflows.append(&mut constraints.overflows);
|
||||
|
||||
// "outlives" represent types/regions that may be touched
|
||||
// by a destructor.
|
||||
result.kinds.append(&mut constraints.outlives);
|
||||
result.overflows.append(&mut constraints.overflows);
|
||||
// If we have even one overflow, we should stop trying to evaluate further --
|
||||
// chances are, the subsequent overflows for this evaluation won't provide useful
|
||||
// information and will just decrease the speed at which we can emit these errors
|
||||
// (since we'll be printing for just that much longer for the often enormous types
|
||||
// that result here).
|
||||
if !result.overflows.is_empty() {
|
||||
break;
|
||||
}
|
||||
|
||||
// If we have even one overflow, we should stop trying to evaluate further --
|
||||
// chances are, the subsequent overflows for this evaluation won't provide useful
|
||||
// information and will just decrease the speed at which we can emit these errors
|
||||
// (since we'll be printing for just that much longer for the often enormous types
|
||||
// that result here).
|
||||
if !result.overflows.is_empty() {
|
||||
break;
|
||||
}
|
||||
// dtorck types are "types that will get dropped but which
|
||||
// do not themselves define a destructor", more or less. We have
|
||||
// to push them onto the stack to be expanded.
|
||||
for ty in constraints.dtorck_types.drain(..) {
|
||||
let Normalized { value: ty, obligations } =
|
||||
ocx.infcx.at(&cause, param_env).normalize(ty)?;
|
||||
ocx.register_obligations(obligations);
|
||||
|
||||
// dtorck types are "types that will get dropped but which
|
||||
// do not themselves define a destructor", more or less. We have
|
||||
// to push them onto the stack to be expanded.
|
||||
for ty in constraints.dtorck_types.drain(..) {
|
||||
match infcx.at(&cause, param_env).normalize(ty) {
|
||||
Ok(Normalized { value: ty, obligations }) => {
|
||||
fulfill_cx.register_predicate_obligations(infcx, obligations);
|
||||
debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
|
||||
|
||||
debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
|
||||
match ty.kind() {
|
||||
// All parameters live for the duration of the
|
||||
// function.
|
||||
ty::Param(..) => {}
|
||||
|
||||
match ty.kind() {
|
||||
// All parameters live for the duration of the
|
||||
// function.
|
||||
ty::Param(..) => {}
|
||||
// A projection that we couldn't resolve - it
|
||||
// might have a destructor.
|
||||
ty::Projection(..) | ty::Opaque(..) => {
|
||||
result.kinds.push(ty.into());
|
||||
}
|
||||
|
||||
// A projection that we couldn't resolve - it
|
||||
// might have a destructor.
|
||||
ty::Projection(..) | ty::Opaque(..) => {
|
||||
result.kinds.push(ty.into());
|
||||
}
|
||||
|
||||
_ => {
|
||||
if ty_set.insert(ty) {
|
||||
ty_stack.push((ty, depth + 1));
|
||||
}
|
||||
_ => {
|
||||
if ty_set.insert(ty) {
|
||||
ty_stack.push((ty, depth + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We don't actually expect to fail to normalize.
|
||||
// That implies a WF error somewhere else.
|
||||
Err(NoSolution) => {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debug!("dropck_outlives: result = {:#?}", result);
|
||||
|
||||
infcx.make_canonicalized_query_response(canonical_inference_vars, result, &mut *fulfill_cx)
|
||||
debug!("dropck_outlives: result = {:#?}", result);
|
||||
Ok(result)
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns a set of constraints that needs to be satisfied in
|
||||
|
@ -1464,6 +1464,19 @@ pub(crate) mod builtin {
|
||||
/* compiler built-in */
|
||||
}
|
||||
|
||||
/// Attribute macro used to apply derive macros for implementing traits
|
||||
/// in a const context.
|
||||
///
|
||||
/// See [the reference] for more info.
|
||||
///
|
||||
/// [the reference]: ../../../reference/attributes/derive.html
|
||||
#[unstable(feature = "derive_const", issue = "none")]
|
||||
#[rustc_builtin_macro]
|
||||
#[cfg(not(bootstrap))]
|
||||
pub macro derive_const($item:item) {
|
||||
/* compiler built-in */
|
||||
}
|
||||
|
||||
/// Attribute macro applied to a function to turn it into a unit test.
|
||||
///
|
||||
/// See [the reference] for more info.
|
||||
|
@ -81,6 +81,10 @@ pub use crate::macros::builtin::alloc_error_handler;
|
||||
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
|
||||
pub use crate::macros::builtin::{bench, derive, global_allocator, test, test_case};
|
||||
|
||||
#[unstable(feature = "derive_const", issue = "none")]
|
||||
#[cfg(not(bootstrap))]
|
||||
pub use crate::macros::builtin::derive_const;
|
||||
|
||||
#[unstable(
|
||||
feature = "cfg_accessible",
|
||||
issue = "64797",
|
||||
|
@ -65,6 +65,10 @@ pub use core::prelude::v1::alloc_error_handler;
|
||||
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
|
||||
pub use core::prelude::v1::{bench, derive, global_allocator, test, test_case};
|
||||
|
||||
#[unstable(feature = "derive_const", issue = "none")]
|
||||
#[cfg(not(bootstrap))]
|
||||
pub use core::prelude::v1::derive_const;
|
||||
|
||||
// Do not `doc(no_inline)` either.
|
||||
#[unstable(
|
||||
feature = "cfg_accessible",
|
||||
|
@ -8,7 +8,8 @@
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.setting-line .radio-line input {
|
||||
.setting-line .radio-line input,
|
||||
.setting-line .toggle input {
|
||||
margin-right: 0.3em;
|
||||
height: 1.2rem;
|
||||
width: 1.2rem;
|
||||
@ -17,9 +18,18 @@
|
||||
outline: none;
|
||||
-webkit-appearance: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.setting-line .radio-line input {
|
||||
border-radius: 50%;
|
||||
}
|
||||
.setting-line .radio-line input + span {
|
||||
.setting-line .toggle input:checked {
|
||||
content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40">\
|
||||
<path d="M7,25L17,32L33,12" fill="none" stroke="black" stroke-width="5"/>\
|
||||
<path d="M7,23L17,30L33,10" fill="none" stroke="white" stroke-width="5"/></svg>');
|
||||
}
|
||||
|
||||
.setting-line .radio-line input + span,
|
||||
.setting-line .toggle span {
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
|
||||
@ -49,37 +59,6 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.toggle input {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.slider {
|
||||
position: relative;
|
||||
width: 45px;
|
||||
min-width: 45px;
|
||||
display: block;
|
||||
height: 28px;
|
||||
margin-right: 20px;
|
||||
cursor: pointer;
|
||||
background-color: #ccc;
|
||||
transition: .3s;
|
||||
}
|
||||
|
||||
.slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 19px;
|
||||
width: 19px;
|
||||
left: 4px;
|
||||
bottom: 4px;
|
||||
transition: .3s;
|
||||
}
|
||||
|
||||
input:checked + .slider:before {
|
||||
transform: translateX(19px);
|
||||
}
|
||||
|
||||
.setting-line > .sub-settings {
|
||||
padding-left: 42px;
|
||||
width: 100%;
|
||||
@ -94,7 +73,11 @@ input:checked + .slider:before {
|
||||
box-shadow: inset 0 0 0 3px var(--main-background-color);
|
||||
background-color: var(--settings-input-color);
|
||||
}
|
||||
.setting-line .radio-line input:focus {
|
||||
.setting-line .toggle input:checked {
|
||||
background-color: var(--settings-input-color);
|
||||
}
|
||||
.setting-line .radio-line input:focus,
|
||||
.setting-line .toggle input:focus {
|
||||
box-shadow: 0 0 1px 1px var(--settings-input-color);
|
||||
}
|
||||
/* In here we combine both `:focus` and `:checked` properties. */
|
||||
@ -102,9 +85,7 @@ input:checked + .slider:before {
|
||||
box-shadow: inset 0 0 0 3px var(--main-background-color),
|
||||
0 0 2px 2px var(--settings-input-color);
|
||||
}
|
||||
.setting-line .radio-line input:hover {
|
||||
.setting-line .radio-line input:hover,
|
||||
.setting-line .toggle input:hover {
|
||||
border-color: var(--settings-input-color) !important;
|
||||
}
|
||||
input:checked + .slider {
|
||||
background-color: var(--settings-input-color);
|
||||
}
|
||||
|
@ -77,16 +77,6 @@ Original by Dempfi (https://github.com/dempfi/ayu)
|
||||
--crate-search-hover-border: #e0e0e0;
|
||||
}
|
||||
|
||||
.slider {
|
||||
background-color: #ccc;
|
||||
}
|
||||
.slider:before {
|
||||
background-color: white;
|
||||
}
|
||||
input:focus + .slider {
|
||||
box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3);
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
color: white;
|
||||
}
|
||||
|
@ -72,16 +72,6 @@
|
||||
--crate-search-hover-border: #2196f3;
|
||||
}
|
||||
|
||||
.slider {
|
||||
background-color: #ccc;
|
||||
}
|
||||
.slider:before {
|
||||
background-color: white;
|
||||
}
|
||||
input:focus + .slider {
|
||||
box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3);
|
||||
}
|
||||
|
||||
.content .item-info::before { color: #ccc; }
|
||||
|
||||
body.source .example-wrap pre.rust a {
|
||||
|
@ -69,15 +69,6 @@
|
||||
--crate-search-hover-border: #717171;
|
||||
}
|
||||
|
||||
.slider {
|
||||
background-color: #ccc;
|
||||
}
|
||||
.slider:before {
|
||||
background-color: white;
|
||||
}
|
||||
input:focus + .slider {
|
||||
box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3);
|
||||
}
|
||||
|
||||
.content .item-info::before { color: #ccc; }
|
||||
|
||||
|
@ -66,8 +66,7 @@
|
||||
|
||||
function setEvents(settingsElement) {
|
||||
updateLightAndDark();
|
||||
onEachLazy(settingsElement.getElementsByClassName("slider"), elem => {
|
||||
const toggle = elem.previousElementSibling;
|
||||
onEachLazy(settingsElement.querySelectorAll("input[type=\"checkbox\"]"), toggle => {
|
||||
const settingId = toggle.id;
|
||||
const settingValue = getSettingValue(settingId);
|
||||
if (settingValue !== null) {
|
||||
@ -139,7 +138,6 @@
|
||||
const checked = setting["default"] === true ? " checked" : "";
|
||||
output += `<label class="toggle">\
|
||||
<input type="checkbox" id="${js_data_name}"${checked}>\
|
||||
<span class="slider"></span>\
|
||||
<span class="label">${setting_name}</span>\
|
||||
</label>`;
|
||||
}
|
||||
|
@ -30,10 +30,10 @@ wait-for: "#settings"
|
||||
assert-css: ("#settings", {"display": "block"})
|
||||
|
||||
// Then, click the toggle button.
|
||||
click: "input#line-numbers + .slider"
|
||||
click: "input#line-numbers"
|
||||
wait-for: 100 // wait-for-false does not exist
|
||||
assert-false: "pre.example-line-numbers"
|
||||
|
||||
// Finally, turn it on again.
|
||||
click: "input#line-numbers + .slider"
|
||||
click: "input#line-numbers"
|
||||
wait-for: "pre.example-line-numbers"
|
||||
|
@ -48,7 +48,8 @@ assert: ".setting-line.hidden #preferred-light-theme"
|
||||
assert-property: ("#theme .choices #theme-dark", {"checked": "true"})
|
||||
|
||||
// Some style checks...
|
||||
// First we check the "default" display.
|
||||
move-cursor-to: "#settings-menu > a"
|
||||
// First we check the "default" display for radio buttons.
|
||||
assert-css: (
|
||||
"#theme-dark",
|
||||
{
|
||||
@ -57,7 +58,7 @@ assert-css: (
|
||||
},
|
||||
)
|
||||
assert-css: ("#theme-light", {"border-color": "rgb(221, 221, 221)", "box-shadow": "none"})
|
||||
// Let's start with the hover.
|
||||
// Let's start with the hover for radio buttons.
|
||||
move-cursor-to: "#theme-dark"
|
||||
assert-css: (
|
||||
"#theme-dark",
|
||||
@ -69,7 +70,7 @@ assert-css: (
|
||||
move-cursor-to: "#theme-light"
|
||||
assert-css: ("#theme-light", {"border-color": "rgb(33, 150, 243)", "box-shadow": "none"})
|
||||
move-cursor-to: "#theme-ayu"
|
||||
// Let's now check with the focus.
|
||||
// Let's now check with the focus for radio buttons.
|
||||
focus: "#theme-dark"
|
||||
assert-css: (
|
||||
"#theme-dark",
|
||||
@ -86,7 +87,7 @@ assert-css: (
|
||||
"box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px",
|
||||
},
|
||||
)
|
||||
// Now we check we both focus and hover.
|
||||
// Now we check we both focus and hover for radio buttons.
|
||||
move-cursor-to: "#theme-dark"
|
||||
focus: "#theme-dark"
|
||||
assert-css: (
|
||||
@ -106,6 +107,80 @@ assert-css: (
|
||||
},
|
||||
)
|
||||
|
||||
// First we check the "default" display for toggles.
|
||||
assert-css: (
|
||||
"#auto-hide-large-items",
|
||||
{
|
||||
"background-color": "rgb(33, 150, 243)",
|
||||
"border-color": "rgb(221, 221, 221)",
|
||||
},
|
||||
)
|
||||
assert-css: (
|
||||
"#use-system-theme",
|
||||
{
|
||||
"background-color": "rgba(0, 0, 0, 0)",
|
||||
"border-color": "rgb(221, 221, 221)",
|
||||
}
|
||||
)
|
||||
// Let's start with the hover for toggles.
|
||||
move-cursor-to: "#auto-hide-large-items"
|
||||
assert-css: (
|
||||
"#auto-hide-large-items",
|
||||
{
|
||||
"background-color": "rgb(33, 150, 243)",
|
||||
"border-color": "rgb(33, 150, 243)",
|
||||
},
|
||||
)
|
||||
move-cursor-to: "#use-system-theme"
|
||||
assert-css: (
|
||||
"#use-system-theme",
|
||||
{
|
||||
"background-color": "rgba(0, 0, 0, 0)",
|
||||
"border-color": "rgb(33, 150, 243)",
|
||||
}
|
||||
)
|
||||
move-cursor-to: "#settings-menu > a"
|
||||
// Let's now check with the focus for toggles.
|
||||
focus: "#auto-hide-large-items"
|
||||
assert-css: (
|
||||
"#auto-hide-large-items",
|
||||
{
|
||||
"background-color": "rgb(33, 150, 243)",
|
||||
"border-color": "rgb(221, 221, 221)",
|
||||
"box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px",
|
||||
},
|
||||
)
|
||||
focus: "#use-system-theme"
|
||||
assert-css: (
|
||||
"#use-system-theme",
|
||||
{
|
||||
"background-color": "rgba(0, 0, 0, 0)",
|
||||
"border-color": "rgb(221, 221, 221)",
|
||||
"box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px",
|
||||
},
|
||||
)
|
||||
// Now we check we both focus and hover for toggles.
|
||||
move-cursor-to: "#auto-hide-large-items"
|
||||
focus: "#auto-hide-large-items"
|
||||
assert-css: (
|
||||
"#auto-hide-large-items",
|
||||
{
|
||||
"background-color": "rgb(33, 150, 243)",
|
||||
"border-color": "rgb(33, 150, 243)",
|
||||
"box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px",
|
||||
},
|
||||
)
|
||||
move-cursor-to: "#use-system-theme"
|
||||
focus: "#use-system-theme"
|
||||
assert-css: (
|
||||
"#use-system-theme",
|
||||
{
|
||||
"background-color": "rgba(0, 0, 0, 0)",
|
||||
"border-color": "rgb(33, 150, 243)",
|
||||
"box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px",
|
||||
},
|
||||
)
|
||||
|
||||
// We now switch the display.
|
||||
click: "#use-system-theme"
|
||||
// Wait for the hidden element to show up.
|
||||
@ -118,7 +193,7 @@ assert: ".setting-line.hidden #theme"
|
||||
assert-text: ("#preferred-dark-theme .setting-name", "Preferred dark theme")
|
||||
assert-text: ("#preferred-light-theme .setting-name", "Preferred light theme")
|
||||
|
||||
// We now check that clicking on the "sliders"' text is like clicking on the slider.
|
||||
// We now check that clicking on the toggles' text is like clicking on the checkbox.
|
||||
// To test it, we use the "Disable keyboard shortcuts".
|
||||
local-storage: {"rustdoc-disable-shortcuts": "false"}
|
||||
click: ".setting-line:last-child .toggle .label"
|
||||
@ -141,10 +216,7 @@ assert-css: ("#settings-menu .popover", {"display": "none"})
|
||||
// Now we go to the settings page to check that the CSS is loaded as expected.
|
||||
goto: "file://" + |DOC_PATH| + "/settings.html"
|
||||
wait-for: "#settings"
|
||||
assert-css: (
|
||||
".setting-line .toggle .slider",
|
||||
{"width": "45px", "margin-right": "20px", "border": "0px none rgb(0, 0, 0)"},
|
||||
)
|
||||
assert-css: (".setting-line", {"position": "relative"})
|
||||
|
||||
assert-attribute-false: ("#settings", {"class": "popover"}, CONTAINS)
|
||||
compare-elements-position: (".sub form", "#settings", ("x"))
|
||||
@ -162,4 +234,4 @@ reload:
|
||||
size: (300, 1000)
|
||||
click: "#settings-menu"
|
||||
wait-for: "#settings"
|
||||
assert-css: ("#settings .slider", {"width": "45px"}, ALL)
|
||||
assert-css: (".setting-line", {"position": "relative"})
|
||||
|
@ -36,7 +36,7 @@ error: attribute should be applied to a function definition
|
||||
--> $DIR/naked-invalid-attr.rs:5:1
|
||||
|
|
||||
LL | #![naked]
|
||||
| ^^^^^^^^^
|
||||
| ^^^^^^^^^ cannot be applied to crates
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
@ -110,19 +110,19 @@ error: attribute should be applied to an `extern crate` item
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:25:1
|
||||
|
|
||||
LL | #![no_link]
|
||||
| ^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^ not an `extern crate` item
|
||||
|
||||
error: attribute should be applied to a free function, impl method or static
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:27:1
|
||||
|
|
||||
LL | #![export_name = "2200"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ not a free function, impl method or static
|
||||
|
||||
error[E0518]: attribute should be applied to function or closure
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:29:1
|
||||
|
|
||||
LL | #![inline]
|
||||
| ^^^^^^^^^^
|
||||
| ^^^^^^^^^^ not a function or closure
|
||||
|
||||
error: `macro_export` attribute cannot be used at crate level
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:12:1
|
||||
|
@ -1,6 +1,6 @@
|
||||
//~ NOTE not a function
|
||||
//~| NOTE not a foreign function or static
|
||||
//~| NOTE not a function or static
|
||||
//~| NOTE cannot be applied to crates
|
||||
//~| NOTE not an `extern` block
|
||||
// This test enumerates as many compiler-builtin ungated attributes as
|
||||
// possible (that is, all the mutually compatible ones), and checks
|
||||
|
@ -403,7 +403,7 @@ warning: attribute should be applied to a function definition
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:62:1
|
||||
|
|
||||
LL | #![cold]
|
||||
| ^^^^^^^^
|
||||
| ^^^^^^^^ cannot be applied to crates
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
|
||||
@ -411,7 +411,7 @@ warning: attribute should be applied to an `extern` block with non-Rust ABI
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:64:1
|
||||
|
|
||||
LL | #![link()]
|
||||
| ^^^^^^^^^^
|
||||
| ^^^^^^^^^^ not an `extern` block
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
|
||||
@ -419,7 +419,7 @@ warning: attribute should be applied to a foreign function or static
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:66:1
|
||||
|
|
||||
LL | #![link_name = "1900"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ not a foreign function or static
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
|
||||
@ -427,7 +427,7 @@ warning: attribute should be applied to a function or static
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:69:1
|
||||
|
|
||||
LL | #![link_section = "1800"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ not a function or static
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
|
||||
|
51
src/test/ui/impl-trait/in-trait/method-signature-matches.rs
Normal file
51
src/test/ui/impl-trait/in-trait/method-signature-matches.rs
Normal file
@ -0,0 +1,51 @@
|
||||
// edition: 2021
|
||||
|
||||
#![feature(return_position_impl_trait_in_trait, async_fn_in_trait)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
trait Uwu {
|
||||
fn owo(x: ()) -> impl Sized;
|
||||
}
|
||||
|
||||
impl Uwu for () {
|
||||
fn owo(_: u8) {}
|
||||
//~^ ERROR method `owo` has an incompatible type for trait
|
||||
}
|
||||
|
||||
trait AsyncUwu {
|
||||
async fn owo(x: ()) {}
|
||||
}
|
||||
|
||||
impl AsyncUwu for () {
|
||||
async fn owo(_: u8) {}
|
||||
//~^ ERROR method `owo` has an incompatible type for trait
|
||||
}
|
||||
|
||||
trait TooMuch {
|
||||
fn calm_down_please() -> impl Sized;
|
||||
}
|
||||
|
||||
impl TooMuch for () {
|
||||
fn calm_down_please(_: (), _: (), _: ()) {}
|
||||
//~^ ERROR method `calm_down_please` has 3 parameters but the declaration in trait `TooMuch::calm_down_please` has 0
|
||||
}
|
||||
|
||||
trait TooLittle {
|
||||
fn come_on_a_little_more_effort(_: (), _: (), _: ()) -> impl Sized;
|
||||
}
|
||||
|
||||
impl TooLittle for () {
|
||||
fn come_on_a_little_more_effort() {}
|
||||
//~^ ERROR method `come_on_a_little_more_effort` has 0 parameters but the declaration in trait `TooLittle::come_on_a_little_more_effort` has 3
|
||||
}
|
||||
|
||||
trait Lifetimes {
|
||||
fn early<'early, T>(x: &'early T) -> impl Sized;
|
||||
}
|
||||
|
||||
impl Lifetimes for () {
|
||||
fn early<'late, T>(_: &'late ()) {}
|
||||
//~^ ERROR method `early` has an incompatible type for trait
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,84 @@
|
||||
error[E0053]: method `owo` has an incompatible type for trait
|
||||
--> $DIR/method-signature-matches.rs:11:15
|
||||
|
|
||||
LL | fn owo(_: u8) {}
|
||||
| ^^
|
||||
| |
|
||||
| expected `()`, found `u8`
|
||||
| help: change the parameter type to match the trait: `()`
|
||||
|
|
||||
note: type in trait
|
||||
--> $DIR/method-signature-matches.rs:7:15
|
||||
|
|
||||
LL | fn owo(x: ()) -> impl Sized;
|
||||
| ^^
|
||||
= note: expected fn pointer `fn(())`
|
||||
found fn pointer `fn(u8)`
|
||||
|
||||
error[E0053]: method `owo` has an incompatible type for trait
|
||||
--> $DIR/method-signature-matches.rs:20:21
|
||||
|
|
||||
LL | async fn owo(_: u8) {}
|
||||
| ^^
|
||||
| |
|
||||
| expected `()`, found `u8`
|
||||
| help: change the parameter type to match the trait: `()`
|
||||
|
|
||||
note: while checking the return type of the `async fn`
|
||||
--> $DIR/method-signature-matches.rs:20:25
|
||||
|
|
||||
LL | async fn owo(_: u8) {}
|
||||
| ^ checked the `Output` of this `async fn`, expected opaque type
|
||||
note: while checking the return type of the `async fn`
|
||||
--> $DIR/method-signature-matches.rs:20:25
|
||||
|
|
||||
LL | async fn owo(_: u8) {}
|
||||
| ^ checked the `Output` of this `async fn`, found opaque type
|
||||
note: type in trait
|
||||
--> $DIR/method-signature-matches.rs:16:21
|
||||
|
|
||||
LL | async fn owo(x: ()) {}
|
||||
| ^^
|
||||
= note: expected fn pointer `fn(()) -> _`
|
||||
found fn pointer `fn(u8) -> _`
|
||||
|
||||
error[E0050]: method `calm_down_please` has 3 parameters but the declaration in trait `TooMuch::calm_down_please` has 0
|
||||
--> $DIR/method-signature-matches.rs:29:28
|
||||
|
|
||||
LL | fn calm_down_please() -> impl Sized;
|
||||
| ------------------------------------ trait requires 0 parameters
|
||||
...
|
||||
LL | fn calm_down_please(_: (), _: (), _: ()) {}
|
||||
| ^^^^^^^^^^^^^^^^ expected 0 parameters, found 3
|
||||
|
||||
error[E0050]: method `come_on_a_little_more_effort` has 0 parameters but the declaration in trait `TooLittle::come_on_a_little_more_effort` has 3
|
||||
--> $DIR/method-signature-matches.rs:38:5
|
||||
|
|
||||
LL | fn come_on_a_little_more_effort(_: (), _: (), _: ()) -> impl Sized;
|
||||
| ---------------- trait requires 3 parameters
|
||||
...
|
||||
LL | fn come_on_a_little_more_effort() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 3 parameters, found 0
|
||||
|
||||
error[E0053]: method `early` has an incompatible type for trait
|
||||
--> $DIR/method-signature-matches.rs:47:27
|
||||
|
|
||||
LL | fn early<'late, T>(_: &'late ()) {}
|
||||
| - ^^^^^^^^^
|
||||
| | |
|
||||
| | expected type parameter `T`, found `()`
|
||||
| | help: change the parameter type to match the trait: `&'early T`
|
||||
| this type parameter
|
||||
|
|
||||
note: type in trait
|
||||
--> $DIR/method-signature-matches.rs:43:28
|
||||
|
|
||||
LL | fn early<'early, T>(x: &'early T) -> impl Sized;
|
||||
| ^^^^^^^^^
|
||||
= note: expected fn pointer `fn(&'early T)`
|
||||
found fn pointer `fn(&())`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0050, E0053.
|
||||
For more information about an error, try `rustc --explain E0050`.
|
@ -2,18 +2,28 @@ error: cannot find attribute `derive_Clone` in this scope
|
||||
--> $DIR/issue-32655.rs:3:11
|
||||
|
|
||||
LL | #[derive_Clone]
|
||||
| ^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `derive_const`
|
||||
...
|
||||
LL | foo!();
|
||||
| ------ in this macro invocation
|
||||
|
|
||||
::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||
|
|
||||
LL | pub macro derive_const($item:item) {
|
||||
| ---------------------- similarly named attribute macro `derive_const` defined here
|
||||
|
|
||||
= note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: cannot find attribute `derive_Clone` in this scope
|
||||
--> $DIR/issue-32655.rs:15:7
|
||||
|
|
||||
LL | #[derive_Clone]
|
||||
| ^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `derive_const`
|
||||
|
|
||||
::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||
|
|
||||
LL | pub macro derive_const($item:item) {
|
||||
| ---------------------- similarly named attribute macro `derive_const` defined here
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -2,10 +2,7 @@ error[E0428]: the name `A` is defined multiple times
|
||||
--> $DIR/issue-69396-const-no-type-in-macro.rs:4:13
|
||||
|
|
||||
LL | const A = "A".$fn();
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `A` redefined here
|
||||
| previous definition of the value `A` here
|
||||
| ^^^^^^^^^^^^^^^^^^^^ `A` redefined here
|
||||
...
|
||||
LL | / suite! {
|
||||
LL | | len;
|
||||
|
@ -1,5 +1,4 @@
|
||||
fn main() {
|
||||
//~^ NOTE required by a bound in this
|
||||
let whatever: [u32; 10] = (0..10).collect();
|
||||
//~^ ERROR an array of type `[u32; 10]` cannot be built directly from an iterator
|
||||
//~| NOTE try collecting into a `Vec<{integer}>`, then using `.try_into()`
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0277]: an array of type `[u32; 10]` cannot be built directly from an iterator
|
||||
--> $DIR/collect-into-array.rs:3:31
|
||||
--> $DIR/collect-into-array.rs:2:31
|
||||
|
|
||||
LL | let whatever: [u32; 10] = (0..10).collect();
|
||||
| ^^^^^^^ ------- required by a bound introduced by this call
|
||||
|
@ -1,6 +1,4 @@
|
||||
fn process_slice(data: &[i32]) {
|
||||
//~^ NOTE required by a bound in this
|
||||
//~| NOTE required by a bound in this
|
||||
todo!()
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
|
||||
--> $DIR/collect-into-slice.rs:8:9
|
||||
--> $DIR/collect-into-slice.rs:6:9
|
||||
|
|
||||
LL | let some_generated_vec = (0..10).collect();
|
||||
| ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
@ -9,7 +9,7 @@ LL | let some_generated_vec = (0..10).collect();
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
|
||||
--> $DIR/collect-into-slice.rs:8:38
|
||||
--> $DIR/collect-into-slice.rs:6:38
|
||||
|
|
||||
LL | let some_generated_vec = (0..10).collect();
|
||||
| ^^^^^^^ doesn't have a size known at compile-time
|
||||
@ -22,7 +22,7 @@ LL | fn collect<B: FromIterator<Self::Item>>(self) -> B
|
||||
| ^ required by this bound in `collect`
|
||||
|
||||
error[E0277]: a slice of type `[i32]` cannot be built since `[i32]` has no definite size
|
||||
--> $DIR/collect-into-slice.rs:8:30
|
||||
--> $DIR/collect-into-slice.rs:6:30
|
||||
|
|
||||
LL | let some_generated_vec = (0..10).collect();
|
||||
| ^^^^^^^ ------- required by a bound introduced by this call
|
||||
|
@ -0,0 +1,4 @@
|
||||
#[derive_const(Default)] //~ ERROR use of unstable library feature
|
||||
pub struct S;
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,11 @@
|
||||
error[E0658]: use of unstable library feature 'derive_const'
|
||||
--> $DIR/derive-const-gate.rs:1:3
|
||||
|
|
||||
LL | #[derive_const(Default)]
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= help: add `#![feature(derive_const)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
@ -0,0 +1,13 @@
|
||||
#![feature(derive_const)]
|
||||
|
||||
pub struct A;
|
||||
|
||||
impl Default for A {
|
||||
fn default() -> A { A }
|
||||
}
|
||||
|
||||
#[derive_const(Default)]
|
||||
pub struct S(A);
|
||||
//~^ cannot call non-const fn
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,14 @@
|
||||
error[E0015]: cannot call non-const fn `<A as Default>::default` in constant functions
|
||||
--> $DIR/derive-const-non-const-type.rs:10:14
|
||||
|
|
||||
LL | #[derive_const(Default)]
|
||||
| ------- in this derive macro expansion
|
||||
LL | pub struct S(A);
|
||||
| ^
|
||||
|
|
||||
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||
= note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0015`.
|
@ -0,0 +1,19 @@
|
||||
// check-pass
|
||||
#![feature(const_trait_impl, const_cmp, const_default_impls, derive_const)]
|
||||
|
||||
pub struct A;
|
||||
|
||||
impl const Default for A {
|
||||
fn default() -> A { A }
|
||||
}
|
||||
|
||||
impl const PartialEq for A {
|
||||
fn eq(&self, _: &A) -> bool { true }
|
||||
}
|
||||
|
||||
#[derive_const(Default, PartialEq)]
|
||||
pub struct S((), A);
|
||||
|
||||
const _: () = assert!(S((), A) == S::default());
|
||||
|
||||
fn main() {}
|
@ -1 +1 @@
|
||||
Subproject commit 9286a1beba5b28b115bad67de2ae91fb1c61eb0b
|
||||
Subproject commit a3dfea71ca0c888a88111086898aa833c291d497
|
@ -573,6 +573,7 @@ fallback = [
|
||||
"/src/llvm-project" = ["@cuviper"]
|
||||
"/src/rustdoc-json-types" = ["rustdoc"]
|
||||
"/src/stage0.json" = ["bootstrap"]
|
||||
"/src/test/ui" = ["compiler"]
|
||||
"/src/tools/cargo" = ["@ehuss", "@joshtriplett"]
|
||||
"/src/tools/compiletest" = ["bootstrap"]
|
||||
"/src/tools/linkchecker" = ["@ehuss"]
|
||||
|
Loading…
Reference in New Issue
Block a user