diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 1db629c3bdf8d..1d5fa73d228e2 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -1294,7 +1294,7 @@ impl BTreeMap { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K: 'a, V: 'a> IntoIterator for &'a BTreeMap { +impl<'a, K, V> IntoIterator for &'a BTreeMap { type Item = (&'a K, &'a V); type IntoIter = Iter<'a, K, V>; @@ -1363,7 +1363,7 @@ impl Clone for Iter<'_, K, V> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K: 'a, V: 'a> IntoIterator for &'a mut BTreeMap { +impl<'a, K, V> IntoIterator for &'a mut BTreeMap { type Item = (&'a K, &'a mut V); type IntoIter = IterMut<'a, K, V>; diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index a2acc239bd38f..a16970e9fd180 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -656,6 +656,38 @@ impl *const T { self.wrapping_offset((count as isize).wrapping_neg()) } + /// Sets the pointer value to `ptr`. + /// + /// In case `self` is a (fat) pointer to an unsized type, this operation + /// will only affect the pointer part, whereas for (thin) pointers to + /// sized types, this has the same effect as a simple assignment. + /// + /// # Examples + /// + /// This function is primarily useful for allowing byte-wise pointer + /// arithmetic on potentially fat pointers: + /// + /// ``` + /// #![feature(set_ptr_value)] + /// # use core::fmt::Debug; + /// let arr: [i32; 3] = [1, 2, 3]; + /// let mut ptr = &arr[0] as *const dyn Debug; + /// let thin = ptr as *const u8; + /// ptr = ptr.set_ptr_value(unsafe { thin.add(8).cast() }); + /// assert_eq!(unsafe { *(ptr as *const i32) }, 3); + /// ``` + #[unstable(feature = "set_ptr_value", issue = "75091")] + #[inline] + pub fn set_ptr_value(mut self, val: *const ()) -> Self { + let thin = &mut self as *mut *const T as *mut *const (); + // SAFETY: In case of a thin pointer, this operations is identical + // to a simple assignment. In case of a fat pointer, with the current + // fat pointer layout implementation, the first field of such a + // pointer is always the data pointer, which is likewise assigned. + unsafe { *thin = val }; + self + } + /// Reads the value from `self` without moving it. This leaves the /// memory in `self` unchanged. /// diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 17fa90ecc08b5..b47f90c599629 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -712,6 +712,38 @@ impl *mut T { self.wrapping_offset((count as isize).wrapping_neg()) } + /// Sets the pointer value to `ptr`. + /// + /// In case `self` is a (fat) pointer to an unsized type, this operation + /// will only affect the pointer part, whereas for (thin) pointers to + /// sized types, this has the same effect as a simple assignment. + /// + /// # Examples + /// + /// This function is primarily useful for allowing byte-wise pointer + /// arithmetic on potentially fat pointers: + /// + /// ``` + /// #![feature(set_ptr_value)] + /// # use core::fmt::Debug; + /// let mut arr: [i32; 3] = [1, 2, 3]; + /// let mut ptr = &mut arr[0] as *mut dyn Debug; + /// let thin = ptr as *mut u8; + /// ptr = ptr.set_ptr_value(unsafe { thin.add(8).cast() }); + /// assert_eq!(unsafe { *(ptr as *mut i32) }, 3); + /// ``` + #[unstable(feature = "set_ptr_value", issue = "75091")] + #[inline] + pub fn set_ptr_value(mut self, val: *mut ()) -> Self { + let thin = &mut self as *mut *mut T as *mut *mut (); + // SAFETY: In case of a thin pointer, this operations is identical + // to a simple assignment. In case of a fat pointer, with the current + // fat pointer layout implementation, the first field of such a + // pointer is always the data pointer, which is likewise assigned. + unsafe { *thin = val }; + self + } + /// Reads the value from `self` without moving it. This leaves the /// memory in `self` unchanged. /// diff --git a/src/librustc_ast_lowering/expr.rs b/src/librustc_ast_lowering/expr.rs index abd5df537db99..f9e54903a661a 100644 --- a/src/librustc_ast_lowering/expr.rs +++ b/src/librustc_ast_lowering/expr.rs @@ -1067,7 +1067,7 @@ impl<'hir> LoweringContext<'_, 'hir> { .collect(); // Stop if there were any errors when lowering the register classes - if operands.len() != asm.operands.len() { + if operands.len() != asm.operands.len() || sess.asm_arch.is_none() { return hir::ExprKind::Err; } diff --git a/src/librustc_hir/def.rs b/src/librustc_hir/def.rs index af1860ca6bfea..618f3e99c3f04 100644 --- a/src/librustc_hir/def.rs +++ b/src/librustc_hir/def.rs @@ -150,7 +150,7 @@ impl DefKind { } } - pub fn matches_ns(&self, ns: Namespace) -> bool { + pub fn ns(&self) -> Option { match self { DefKind::Mod | DefKind::Struct @@ -163,7 +163,7 @@ impl DefKind { | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::AssocTy - | DefKind::TyParam => ns == Namespace::TypeNS, + | DefKind::TyParam => Some(Namespace::TypeNS), DefKind::Fn | DefKind::Const @@ -171,9 +171,9 @@ impl DefKind { | DefKind::Static | DefKind::Ctor(..) | DefKind::AssocFn - | DefKind::AssocConst => ns == Namespace::ValueNS, + | DefKind::AssocConst => Some(Namespace::ValueNS), - DefKind::Macro(..) => ns == Namespace::MacroNS, + DefKind::Macro(..) => Some(Namespace::MacroNS), // Not namespaced. DefKind::AnonConst @@ -185,7 +185,7 @@ impl DefKind { | DefKind::Use | DefKind::ForeignMod | DefKind::GlobalAsm - | DefKind::Impl => false, + | DefKind::Impl => None, } } } @@ -453,7 +453,7 @@ impl Res { pub fn matches_ns(&self, ns: Namespace) -> bool { match self { - Res::Def(kind, ..) => kind.matches_ns(ns), + Res::Def(kind, ..) => kind.ns() == Some(ns), Res::PrimTy(..) | Res::SelfTy(..) | Res::ToolMod => ns == Namespace::TypeNS, Res::SelfCtor(..) | Res::Local(..) => ns == Namespace::ValueNS, Res::NonMacroAttr(..) => ns == Namespace::MacroNS, diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 52c306688268f..069d333de1834 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -607,6 +607,9 @@ pub fn register_res(cx: &DocContext<'_>, res: Res) -> DefId { Res::Def(DefKind::TyAlias, i) => (i, TypeKind::Typedef), Res::Def(DefKind::Enum, i) => (i, TypeKind::Enum), Res::Def(DefKind::Trait, i) => (i, TypeKind::Trait), + Res::Def(DefKind::AssocTy | DefKind::AssocFn | DefKind::AssocConst, i) => { + (cx.tcx.parent(i).unwrap(), TypeKind::Trait) + } Res::Def(DefKind::Struct, i) => (i, TypeKind::Struct), Res::Def(DefKind::Union, i) => (i, TypeKind::Union), Res::Def(DefKind::Mod, i) => (i, TypeKind::Module), diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index bf7a43236e061..f84486347afcd 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -17,6 +17,7 @@ use rustc_span::symbol::Ident; use rustc_span::symbol::Symbol; use rustc_span::DUMMY_SP; +use std::cell::Cell; use std::ops::Range; use crate::clean::*; @@ -62,11 +63,15 @@ struct LinkCollector<'a, 'tcx> { cx: &'a DocContext<'tcx>, // NOTE: this may not necessarily be a module in the current crate mod_ids: Vec, + /// This is used to store the kind of associated items, + /// because `clean` and the disambiguator code expect them to be different. + /// See the code for associated items on inherent impls for details. + kind_side_channel: Cell>, } impl<'a, 'tcx> LinkCollector<'a, 'tcx> { fn new(cx: &'a DocContext<'tcx>) -> Self { - LinkCollector { cx, mod_ids: Vec::new() } + LinkCollector { cx, mod_ids: Vec::new(), kind_side_channel: Cell::new(None) } } fn variant_field( @@ -174,7 +179,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { fn resolve( &self, path_str: &str, - disambiguator: Option<&str>, + disambiguator: Option, ns: Namespace, current_item: &Option, parent_id: Option, @@ -214,7 +219,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { Res::Def(DefKind::Mod, _) => { // This resolved to a module, but if we were passed `type@`, // we want primitive types to take precedence instead. - if disambiguator == Some("type") { + if disambiguator == Some(Disambiguator::Namespace(Namespace::TypeNS)) { if let Some(prim) = is_primitive(path_str, ns) { if extra_fragment.is_some() { return Err(ErrorKind::AnchorFailure(AnchorFailure::Primitive)); @@ -347,6 +352,10 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { AnchorFailure::AssocConstant })) } else { + // HACK(jynelson): `clean` expects the type, not the associated item. + // but the disambiguator logic expects the associated item. + // Store the kind in a side channel so that only the disambiguator logic looks at it. + self.kind_side_channel.replace(Some(item.kind.as_def_kind())); Ok((ty_res, Some(format!("{}.{}", out, item_name)))) } } else { @@ -415,7 +424,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { AnchorFailure::Method })) } else { - Ok((ty_res, Some(format!("{}.{}", kind, item_name)))) + let res = Res::Def(item.kind.as_def_kind(), item.def_id); + Ok((res, Some(format!("{}.{}", kind, item_name)))) } } else { self.variant_field(path_str, current_item, module_id) @@ -574,46 +584,14 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { }; let resolved_self; let mut path_str; + let disambiguator; let (res, fragment) = { - let mut kind = None; - let mut disambiguator = None; - path_str = if let Some(prefix) = - ["struct@", "enum@", "type@", "trait@", "union@", "module@", "mod@"] - .iter() - .find(|p| link.starts_with(**p)) - { - kind = Some(TypeNS); - disambiguator = Some(&prefix[..prefix.len() - 1]); - link.trim_start_matches(prefix) - } else if let Some(prefix) = - ["const@", "static@", "value@", "function@", "fn@", "method@"] - .iter() - .find(|p| link.starts_with(**p)) - { - kind = Some(ValueNS); - disambiguator = Some(&prefix[..prefix.len() - 1]); - link.trim_start_matches(prefix) - } else if link.ends_with("!()") { - kind = Some(MacroNS); - link.trim_end_matches("!()") - } else if link.ends_with("()") { - kind = Some(ValueNS); - disambiguator = Some("fn"); - link.trim_end_matches("()") - } else if link.starts_with("macro@") { - kind = Some(MacroNS); - disambiguator = Some("macro"); - link.trim_start_matches("macro@") - } else if link.starts_with("derive@") { - kind = Some(MacroNS); - disambiguator = Some("derive"); - link.trim_start_matches("derive@") - } else if link.ends_with('!') { - kind = Some(MacroNS); - disambiguator = Some("macro"); - link.trim_end_matches('!') + path_str = if let Ok((d, path)) = Disambiguator::from_str(&link) { + disambiguator = Some(d); + path } else { - &link[..] + disambiguator = None; + &link } .trim(); @@ -646,7 +624,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { } } - match kind { + match disambiguator.map(Disambiguator::ns) { Some(ns @ ValueNS) => { match self.resolve( path_str, @@ -789,6 +767,42 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { } else { debug!("intra-doc link to {} resolved to {:?}", path_str, res); + // Disallow e.g. linking to enums with `struct@` + if let Res::Def(kind, id) = res { + debug!("saw kind {:?} with disambiguator {:?}", kind, disambiguator); + match (self.kind_side_channel.take().unwrap_or(kind), disambiguator) { + | (DefKind::Const | DefKind::ConstParam | DefKind::AssocConst | DefKind::AnonConst, Some(Disambiguator::Kind(DefKind::Const))) + // NOTE: this allows 'method' to mean both normal functions and associated functions + // This can't cause ambiguity because both are in the same namespace. + | (DefKind::Fn | DefKind::AssocFn, Some(Disambiguator::Kind(DefKind::Fn))) + // These are namespaces; allow anything in the namespace to match + | (_, Some(Disambiguator::Namespace(_))) + // If no disambiguator given, allow anything + | (_, None) + // All of these are valid, so do nothing + => {} + (actual, Some(Disambiguator::Kind(expected))) if actual == expected => {} + (_, Some(Disambiguator::Kind(expected))) => { + // The resolved item did not match the disambiguator; give a better error than 'not found' + let msg = format!("incompatible link kind for `{}`", path_str); + report_diagnostic(cx, &msg, &item, &dox, link_range, |diag, sp| { + // HACK(jynelson): by looking at the source I saw the DefId we pass + // for `expected.descr()` doesn't matter, since it's not a crate + let note = format!("this link resolved to {} {}, which is not {} {}", kind.article(), kind.descr(id), expected.article(), expected.descr(id)); + let suggestion = Disambiguator::display_for(kind, path_str); + let help_msg = format!("to link to the {}, use its disambiguator", kind.descr(id)); + diag.note(¬e); + if let Some(sp) = sp { + diag.span_suggestion(sp, &help_msg, suggestion, Applicability::MaybeIncorrect); + } else { + diag.help(&format!("{}: {}", help_msg, suggestion)); + } + }); + continue; + } + } + } + // item can be non-local e.g. when using #[doc(primitive = "pointer")] if let Some((src_id, dst_id)) = res .opt_def_id() @@ -837,6 +851,94 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { } } +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +enum Disambiguator { + Kind(DefKind), + Namespace(Namespace), +} + +impl Disambiguator { + /// (disambiguator, path_str) + fn from_str(link: &str) -> Result<(Self, &str), ()> { + use Disambiguator::{Kind, Namespace as NS}; + + let find_suffix = || { + let suffixes = [ + ("!()", DefKind::Macro(MacroKind::Bang)), + ("()", DefKind::Fn), + ("!", DefKind::Macro(MacroKind::Bang)), + ]; + for &(suffix, kind) in &suffixes { + if link.ends_with(suffix) { + return Ok((Kind(kind), link.trim_end_matches(suffix))); + } + } + Err(()) + }; + + if let Some(idx) = link.find('@') { + let (prefix, rest) = link.split_at(idx); + let d = match prefix { + "struct" => Kind(DefKind::Struct), + "enum" => Kind(DefKind::Enum), + "trait" => Kind(DefKind::Trait), + "union" => Kind(DefKind::Union), + "module" | "mod" => Kind(DefKind::Mod), + "const" | "constant" => Kind(DefKind::Const), + "static" => Kind(DefKind::Static), + "function" | "fn" | "method" => Kind(DefKind::Fn), + "derive" => Kind(DefKind::Macro(MacroKind::Derive)), + "type" => NS(Namespace::TypeNS), + "value" => NS(Namespace::ValueNS), + "macro" => NS(Namespace::MacroNS), + _ => return find_suffix(), + }; + Ok((d, &rest[1..])) + } else { + find_suffix() + } + } + + fn display_for(kind: DefKind, path_str: &str) -> String { + if kind == DefKind::Macro(MacroKind::Bang) { + return format!("{}!", path_str); + } else if kind == DefKind::Fn || kind == DefKind::AssocFn { + return format!("{}()", path_str); + } + let prefix = match kind { + DefKind::Struct => "struct", + DefKind::Enum => "enum", + DefKind::Trait => "trait", + DefKind::Union => "union", + DefKind::Mod => "mod", + DefKind::Const | DefKind::ConstParam | DefKind::AssocConst | DefKind::AnonConst => { + "const" + } + DefKind::Static => "static", + DefKind::Macro(MacroKind::Derive) => "derive", + // Now handle things that don't have a specific disambiguator + _ => match kind + .ns() + .expect("tried to calculate a disambiguator for a def without a namespace?") + { + Namespace::TypeNS => "type", + Namespace::ValueNS => "value", + Namespace::MacroNS => "macro", + }, + }; + format!("{}@{}", prefix, path_str) + } + + fn ns(self) -> Namespace { + match self { + Self::Namespace(n) => n, + Self::Kind(k) => { + k.ns().expect("only DefKinds with a valid namespace can be disambiguators") + } + } + } +} + /// Reports a diagnostic for an intra-doc link. /// /// If no link range is provided, or the source span of the link cannot be determined, the span of diff --git a/src/test/rustdoc-ui/intra-links-disambiguator-mismatch.rs b/src/test/rustdoc-ui/intra-links-disambiguator-mismatch.rs new file mode 100644 index 0000000000000..1a7a2fce7a3f2 --- /dev/null +++ b/src/test/rustdoc-ui/intra-links-disambiguator-mismatch.rs @@ -0,0 +1,68 @@ +#![deny(broken_intra_doc_links)] +//~^ NOTE lint level is defined +pub enum S {} + +macro_rules! m { + () => {}; +} + +static s: usize = 0; +const c: usize = 0; + +trait T {} + +/// Link to [struct@S] +//~^ ERROR incompatible link kind for `S` +//~| NOTE this link resolved +//~| HELP use its disambiguator + +/// Link to [mod@S] +//~^ ERROR incompatible link kind for `S` +//~| NOTE this link resolved +//~| HELP use its disambiguator + +/// Link to [union@S] +//~^ ERROR incompatible link kind for `S` +//~| NOTE this link resolved +//~| HELP use its disambiguator + +/// Link to [trait@S] +//~^ ERROR incompatible link kind for `S` +//~| NOTE this link resolved +//~| HELP use its disambiguator + +/// Link to [struct@T] +//~^ ERROR incompatible link kind for `T` +//~| NOTE this link resolved +//~| HELP use its disambiguator + +/// Link to [derive@m] +//~^ ERROR incompatible link kind for `m` +//~| NOTE this link resolved +//~| HELP use its disambiguator + +/// Link to [const@s] +//~^ ERROR incompatible link kind for `s` +//~| NOTE this link resolved +//~| HELP use its disambiguator + +/// Link to [static@c] +//~^ ERROR incompatible link kind for `c` +//~| NOTE this link resolved +//~| HELP use its disambiguator + +/// Link to [fn@c] +//~^ ERROR incompatible link kind for `c` +//~| NOTE this link resolved +//~| HELP use its disambiguator + +/// Link to [c()] +//~^ ERROR incompatible link kind for `c` +//~| NOTE this link resolved +//~| HELP use its disambiguator + +/// Link to [const@f] +//~^ ERROR incompatible link kind for `f` +//~| NOTE this link resolved +//~| HELP use its disambiguator +pub fn f() {} diff --git a/src/test/rustdoc-ui/intra-links-disambiguator-mismatch.stderr b/src/test/rustdoc-ui/intra-links-disambiguator-mismatch.stderr new file mode 100644 index 0000000000000..9edf838f9d88b --- /dev/null +++ b/src/test/rustdoc-ui/intra-links-disambiguator-mismatch.stderr @@ -0,0 +1,95 @@ +error: incompatible link kind for `S` + --> $DIR/intra-links-disambiguator-mismatch.rs:14:14 + | +LL | /// Link to [struct@S] + | ^^^^^^^^ help: to link to the enum, use its disambiguator: `enum@S` + | +note: the lint level is defined here + --> $DIR/intra-links-disambiguator-mismatch.rs:1:9 + | +LL | #![deny(broken_intra_doc_links)] + | ^^^^^^^^^^^^^^^^^^^^^^ + = note: this link resolved to an enum, which is not a struct + +error: incompatible link kind for `S` + --> $DIR/intra-links-disambiguator-mismatch.rs:19:14 + | +LL | /// Link to [mod@S] + | ^^^^^ help: to link to the enum, use its disambiguator: `enum@S` + | + = note: this link resolved to an enum, which is not a module + +error: incompatible link kind for `S` + --> $DIR/intra-links-disambiguator-mismatch.rs:24:14 + | +LL | /// Link to [union@S] + | ^^^^^^^ help: to link to the enum, use its disambiguator: `enum@S` + | + = note: this link resolved to an enum, which is not a union + +error: incompatible link kind for `S` + --> $DIR/intra-links-disambiguator-mismatch.rs:29:14 + | +LL | /// Link to [trait@S] + | ^^^^^^^ help: to link to the enum, use its disambiguator: `enum@S` + | + = note: this link resolved to an enum, which is not a trait + +error: incompatible link kind for `T` + --> $DIR/intra-links-disambiguator-mismatch.rs:34:14 + | +LL | /// Link to [struct@T] + | ^^^^^^^^ help: to link to the trait, use its disambiguator: `trait@T` + | + = note: this link resolved to a trait, which is not a struct + +error: incompatible link kind for `m` + --> $DIR/intra-links-disambiguator-mismatch.rs:39:14 + | +LL | /// Link to [derive@m] + | ^^^^^^^^ help: to link to the macro, use its disambiguator: `m!` + | + = note: this link resolved to a macro, which is not a derive macro + +error: incompatible link kind for `s` + --> $DIR/intra-links-disambiguator-mismatch.rs:44:14 + | +LL | /// Link to [const@s] + | ^^^^^^^ help: to link to the static, use its disambiguator: `static@s` + | + = note: this link resolved to a static, which is not a constant + +error: incompatible link kind for `c` + --> $DIR/intra-links-disambiguator-mismatch.rs:49:14 + | +LL | /// Link to [static@c] + | ^^^^^^^^ help: to link to the constant, use its disambiguator: `const@c` + | + = note: this link resolved to a constant, which is not a static + +error: incompatible link kind for `c` + --> $DIR/intra-links-disambiguator-mismatch.rs:54:14 + | +LL | /// Link to [fn@c] + | ^^^^ help: to link to the constant, use its disambiguator: `const@c` + | + = note: this link resolved to a constant, which is not a function + +error: incompatible link kind for `c` + --> $DIR/intra-links-disambiguator-mismatch.rs:59:14 + | +LL | /// Link to [c()] + | ^^^ help: to link to the constant, use its disambiguator: `const@c` + | + = note: this link resolved to a constant, which is not a function + +error: incompatible link kind for `f` + --> $DIR/intra-links-disambiguator-mismatch.rs:64:14 + | +LL | /// Link to [const@f] + | ^^^^^^^ help: to link to the function, use its disambiguator: `f()` + | + = note: this link resolved to a function, which is not a constant + +error: aborting due to 11 previous errors + diff --git a/src/test/rustdoc/intra-link-trait-item.rs b/src/test/rustdoc/intra-link-trait-item.rs new file mode 100644 index 0000000000000..54270414c9dfe --- /dev/null +++ b/src/test/rustdoc/intra-link-trait-item.rs @@ -0,0 +1,12 @@ +// ignore-tidy-linelength +#![deny(broken_intra_doc_links)] + +/// Link to [S::assoc_fn()] +/// Link to [Default::default()] +// @has intra_link_trait_item/struct.S.html '//*[@href="../intra_link_trait_item/struct.S.html#method.assoc_fn"]' 'S::assoc_fn()' +// @has - '//*[@href="https://doc.rust-lang.org/nightly/core/default/trait.Default.html#tymethod.default"]' 'Default::default()' +pub struct S; + +impl S { + pub fn assoc_fn() {} +} diff --git a/src/test/ui/asm/bad-arch.rs b/src/test/ui/asm/bad-arch.rs new file mode 100644 index 0000000000000..eeeeb17dd4f3f --- /dev/null +++ b/src/test/ui/asm/bad-arch.rs @@ -0,0 +1,18 @@ +// compile-flags: --target wasm32-unknown-unknown + +#![feature(no_core, lang_items, rustc_attrs)] +#![no_core] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} +#[lang = "sized"] +trait Sized {} + +fn main() { + unsafe { + asm!(""); + //~^ ERROR asm! is unsupported on this target + } +} diff --git a/src/test/ui/asm/bad-arch.stderr b/src/test/ui/asm/bad-arch.stderr new file mode 100644 index 0000000000000..daccc46c6e371 --- /dev/null +++ b/src/test/ui/asm/bad-arch.stderr @@ -0,0 +1,8 @@ +error[E0472]: asm! is unsupported on this target + --> $DIR/bad-arch.rs:15:9 + | +LL | asm!(""); + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/btreemap/btreemap_into_iterator_lifetime.rs b/src/test/ui/btreemap/btreemap_into_iterator_lifetime.rs new file mode 100644 index 0000000000000..fda825bc65e80 --- /dev/null +++ b/src/test/ui/btreemap/btreemap_into_iterator_lifetime.rs @@ -0,0 +1,23 @@ +// check-pass + +use std::collections::{BTreeMap, HashMap}; + +trait Map +where + for<'a> &'a Self: IntoIterator, +{ + type Key; + type Value; +} + +impl Map for HashMap { + type Key = K; + type Value = V; +} + +impl Map for BTreeMap { + type Key = K; + type Value = V; +} + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-asm.rs b/src/test/ui/feature-gates/feature-gate-asm.rs index 753e924f00495..59f04372fff19 100644 --- a/src/test/ui/feature-gates/feature-gate-asm.rs +++ b/src/test/ui/feature-gates/feature-gate-asm.rs @@ -1,4 +1,4 @@ -// ignore-emscripten +// only-x86_64 fn main() { unsafe { diff --git a/src/test/ui/feature-gates/feature-gate-asm2.rs b/src/test/ui/feature-gates/feature-gate-asm2.rs index e9349acb64394..aa63aff1c5e33 100644 --- a/src/test/ui/feature-gates/feature-gate-asm2.rs +++ b/src/test/ui/feature-gates/feature-gate-asm2.rs @@ -1,4 +1,4 @@ -// ignore-emscripten +// only-x86_64 fn main() { unsafe {