Auto merge of #71424 - Dylan-DPC:rollup-iunh61a, r=Dylan-DPC

Rollup of 6 pull requests

Successful merges:

 - #70970 (Detect mistyped associated consts in `Instance::resolve`.)
 - #71203 (Correct await span for async-await error reporting)
 - #71214 (Add error code for inner doc error)
 - #71337 (Moving all rustdoc-ui tests to check-pass)
 - #71412 (Clarify unused_doc_comments note on macro invocations)
 - #71414 (More diagnostic items for Clippy usage)

Failed merges:

r? @ghost
This commit is contained in:
bors 2020-04-22 11:14:23 +00:00
commit 00f677d897
57 changed files with 297 additions and 103 deletions

View File

@ -4295,6 +4295,7 @@ version = "0.0.0"
dependencies = [ dependencies = [
"log", "log",
"rustc_data_structures", "rustc_data_structures",
"rustc_errors",
"rustc_hir", "rustc_hir",
"rustc_infer", "rustc_infer",
"rustc_middle", "rustc_middle",

View File

@ -50,6 +50,7 @@ const MAXIMUM_ZST_CAPACITY: usize = 1 << (64 - 1); // Largest possible power of
/// [`pop_front`]: #method.pop_front /// [`pop_front`]: #method.pop_front
/// [`extend`]: #method.extend /// [`extend`]: #method.extend
/// [`append`]: #method.append /// [`append`]: #method.append
#[cfg_attr(not(test), rustc_diagnostic_item = "vecdeque_type")]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct VecDeque<T> { pub struct VecDeque<T> {
// tail and head are pointers into the buffer. Tail always points // tail and head are pointers into the buffer. Tail always points

View File

@ -278,6 +278,7 @@ use crate::vec::Vec;
/// [`Deref`]: ../../std/ops/trait.Deref.html /// [`Deref`]: ../../std/ops/trait.Deref.html
/// [`as_str()`]: struct.String.html#method.as_str /// [`as_str()`]: struct.String.html#method.as_str
#[derive(PartialOrd, Eq, Ord)] #[derive(PartialOrd, Eq, Ord)]
#[cfg_attr(not(test), rustc_diagnostic_item = "string_type")]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct String { pub struct String {
vec: Vec<u8>, vec: Vec<u8>,

View File

@ -376,6 +376,7 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
def_id, def_id,
tcx.intern_substs(&[]), tcx.intern_substs(&[]),
) )
.unwrap()
.unwrap(), .unwrap(),
), ),
_ => { _ => {

View File

@ -465,6 +465,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
start_def_id, start_def_id,
cx.tcx().intern_substs(&[main_ret_ty.into()]), cx.tcx().intern_substs(&[main_ret_ty.into()]),
) )
.unwrap()
.unwrap(), .unwrap(),
); );
( (

View File

@ -537,6 +537,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
ty::FnDef(def_id, substs) => ( ty::FnDef(def_id, substs) => (
Some( Some(
ty::Instance::resolve(bx.tcx(), ty::ParamEnv::reveal_all(), def_id, substs) ty::Instance::resolve(bx.tcx(), ty::ParamEnv::reveal_all(), def_id, substs)
.unwrap()
.unwrap(), .unwrap(),
), ),
None, None,

View File

@ -432,6 +432,7 @@ E0749: include_str!("./error_codes/E0749.md"),
E0750: include_str!("./error_codes/E0750.md"), E0750: include_str!("./error_codes/E0750.md"),
E0751: include_str!("./error_codes/E0751.md"), E0751: include_str!("./error_codes/E0751.md"),
E0752: include_str!("./error_codes/E0752.md"), E0752: include_str!("./error_codes/E0752.md"),
E0753: include_str!("./error_codes/E0753.md"),
; ;
// E0006, // merged with E0005 // E0006, // merged with E0005
// E0008, // cannot bind by-move into a pattern guard // E0008, // cannot bind by-move into a pattern guard

View File

@ -0,0 +1,31 @@
An inner doc comment was used in an invalid context.
Erroneous code example:
```compile_fail,E0753
fn foo() {}
//! foo
// ^ error!
fn main() {}
```
Inner document can only be used before items. For example:
```
//! A working comment applied to the module!
fn foo() {
//! Another working comment!
}
fn main() {}
```
In case you want to document the item following the doc comment, you might want
to use outer doc comment:
```
/// I am an outer doc comment
#[doc = "I am also an outer doc comment!"]
fn foo() {
// ...
}
```

View File

@ -566,7 +566,7 @@ pub trait LintContext: Sized {
stability::deprecation_suggestion(&mut db, suggestion, span) stability::deprecation_suggestion(&mut db, suggestion, span)
} }
BuiltinLintDiagnostics::UnusedDocComment(span) => { BuiltinLintDiagnostics::UnusedDocComment(span) => {
db.span_label(span, "rustdoc does not generate documentation for macros"); db.span_label(span, "rustdoc does not generate documentation for macro invocations");
db.help("to document an item produced by a macro, \ db.help("to document an item produced by a macro, \
the macro must produce the documentation as part of its expansion"); the macro must produce the documentation as part of its expansion");
} }

View File

@ -39,12 +39,13 @@ impl<'tcx> TyCtxt<'tcx> {
promoted: Option<mir::Promoted>, promoted: Option<mir::Promoted>,
span: Option<Span>, span: Option<Span>,
) -> ConstEvalResult<'tcx> { ) -> ConstEvalResult<'tcx> {
let instance = ty::Instance::resolve(self, param_env, def_id, substs); match ty::Instance::resolve(self, param_env, def_id, substs) {
if let Some(instance) = instance { Ok(Some(instance)) => {
let cid = GlobalId { instance, promoted }; let cid = GlobalId { instance, promoted };
self.const_eval_global_id(param_env, cid, span) self.const_eval_global_id(param_env, cid, span)
} else { }
Err(ErrorHandled::TooGeneric) Ok(None) => Err(ErrorHandled::TooGeneric),
Err(error_reported) => Err(ErrorHandled::Reported(error_reported)),
} }
} }

View File

@ -679,7 +679,7 @@ rustc_queries! {
Codegen { Codegen {
query codegen_fulfill_obligation( query codegen_fulfill_obligation(
key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)
) -> Option<Vtable<'tcx, ()>> { ) -> Result<Vtable<'tcx, ()>, ErrorReported> {
cache_on_disk_if { true } cache_on_disk_if { true }
desc { |tcx| desc { |tcx|
"checking if `{}` fulfills its obligations", "checking if `{}` fulfills its obligations",
@ -1258,8 +1258,19 @@ rustc_queries! {
desc { "looking up enabled feature gates" } desc { "looking up enabled feature gates" }
} }
query resolve_instance(key: (ty::ParamEnv<'tcx>, DefId, SubstsRef<'tcx>)) -> Option<ty::Instance<'tcx>> { /// Attempt to resolve the given `DefId` to an `Instance`, for the
desc { "resolving instance `{:?}` `{:?}` with {:?}", key.1, key.2, key.0 } /// given generics args (`SubstsRef`), returning one of:
/// * `Ok(Some(instance))` on success
/// * `Ok(None)` when the `SubstsRef` are still too generic,
/// and therefore don't allow finding the final `Instance`
/// * `Err(ErrorReported)` when the `Instance` resolution process
/// couldn't complete due to errors elsewhere - this is distinct
/// from `Ok(None)` to avoid misleading diagnostics when an error
/// has already been/will be emitted, for the original cause
query resolve_instance(
key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>
) -> Result<Option<ty::Instance<'tcx>>, ErrorReported> {
desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) }
} }
} }
} }

View File

@ -298,14 +298,14 @@ pub struct ResolvedOpaqueTy<'tcx> {
/// ///
/// ```ignore (pseudo-Rust) /// ```ignore (pseudo-Rust)
/// async move { /// async move {
/// let x: T = ...; /// let x: T = expr;
/// foo.await /// foo.await
/// ... /// ...
/// } /// }
/// ``` /// ```
/// ///
/// Here, we would store the type `T`, the span of the value `x`, and the "scope-span" for /// Here, we would store the type `T`, the span of the value `x`, the "scope-span" for
/// the scope that contains `x`. /// the scope that contains `x`, the expr `T` evaluated from, and the span of `foo.await`.
#[derive(RustcEncodable, RustcDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)] #[derive(RustcEncodable, RustcDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)]
pub struct GeneratorInteriorTypeCause<'tcx> { pub struct GeneratorInteriorTypeCause<'tcx> {
/// Type of the captured binding. /// Type of the captured binding.
@ -314,6 +314,8 @@ pub struct GeneratorInteriorTypeCause<'tcx> {
pub span: Span, pub span: Span,
/// Span of the scope of the captured binding. /// Span of the scope of the captured binding.
pub scope_span: Option<Span>, pub scope_span: Option<Span>,
/// Span of `.await` or `yield` expression.
pub yield_span: Span,
/// Expr which the type evaluated from. /// Expr which the type evaluated from.
pub expr: Option<hir::HirId>, pub expr: Option<hir::HirId>,
} }

View File

@ -1,6 +1,7 @@
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::print::{FmtPrinter, Printer};
use crate::ty::{self, SubstsRef, Ty, TyCtxt, TypeFoldable}; use crate::ty::{self, SubstsRef, Ty, TyCtxt, TypeFoldable};
use rustc_errors::ErrorReported;
use rustc_hir::def::Namespace; use rustc_hir::def::Namespace;
use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::def_id::{CrateNum, DefId};
use rustc_hir::lang_items::DropInPlaceFnLangItem; use rustc_hir::lang_items::DropInPlaceFnLangItem;
@ -268,29 +269,41 @@ impl<'tcx> Instance<'tcx> {
/// this is used to find the precise code that will run for a trait method invocation, /// this is used to find the precise code that will run for a trait method invocation,
/// if known. /// if known.
/// ///
/// Returns `None` if we cannot resolve `Instance` to a specific instance. /// Returns `Ok(None)` if we cannot resolve `Instance` to a specific instance.
/// For example, in a context like this, /// For example, in a context like this,
/// ///
/// ``` /// ```
/// fn foo<T: Debug>(t: T) { ... } /// fn foo<T: Debug>(t: T) { ... }
/// ``` /// ```
/// ///
/// trying to resolve `Debug::fmt` applied to `T` will yield `None`, because we do not /// trying to resolve `Debug::fmt` applied to `T` will yield `Ok(None)`, because we do not
/// know what code ought to run. (Note that this setting is also affected by the /// know what code ought to run. (Note that this setting is also affected by the
/// `RevealMode` in the parameter environment.) /// `RevealMode` in the parameter environment.)
/// ///
/// Presuming that coherence and type-check have succeeded, if this method is invoked /// Presuming that coherence and type-check have succeeded, if this method is invoked
/// in a monomorphic context (i.e., like during codegen), then it is guaranteed to return /// in a monomorphic context (i.e., like during codegen), then it is guaranteed to return
/// `Some`. /// `Ok(Some(instance))`.
///
/// Returns `Err(ErrorReported)` when the `Instance` resolution process
/// couldn't complete due to errors elsewhere - this is distinct
/// from `Ok(None)` to avoid misleading diagnostics when an error
/// has already been/will be emitted, for the original cause
pub fn resolve( pub fn resolve(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
def_id: DefId, def_id: DefId,
substs: SubstsRef<'tcx>, substs: SubstsRef<'tcx>,
) -> Option<Instance<'tcx>> { ) -> Result<Option<Instance<'tcx>>, ErrorReported> {
// All regions in the result of this query are erased, so it's // All regions in the result of this query are erased, so it's
// fine to erase all of the input regions. // fine to erase all of the input regions.
tcx.resolve_instance((tcx.erase_regions(&param_env), def_id, tcx.erase_regions(&substs)))
// HACK(eddyb) erase regions in `substs` first, so that `param_env.and(...)`
// below is more likely to ignore the bounds in scope (e.g. if the only
// generic parameters mentioned by `substs` were lifetime ones).
let substs = tcx.erase_regions(&substs);
// FIXME(eddyb) should this always use `param_env.with_reveal_all()`?
tcx.resolve_instance(tcx.erase_regions(&param_env.and((def_id, substs))))
} }
pub fn resolve_for_fn_ptr( pub fn resolve_for_fn_ptr(
@ -300,7 +313,7 @@ impl<'tcx> Instance<'tcx> {
substs: SubstsRef<'tcx>, substs: SubstsRef<'tcx>,
) -> Option<Instance<'tcx>> { ) -> Option<Instance<'tcx>> {
debug!("resolve(def_id={:?}, substs={:?})", def_id, substs); debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
Instance::resolve(tcx, param_env, def_id, substs).map(|mut resolved| { Instance::resolve(tcx, param_env, def_id, substs).ok().flatten().map(|mut resolved| {
match resolved.def { match resolved.def {
InstanceDef::Item(def_id) if resolved.def.requires_caller_location(tcx) => { InstanceDef::Item(def_id) if resolved.def.requires_caller_location(tcx) => {
debug!(" => fn pointer created for function with #[track_caller]"); debug!(" => fn pointer created for function with #[track_caller]");
@ -332,7 +345,7 @@ impl<'tcx> Instance<'tcx> {
debug!(" => associated item with unsizeable self: Self"); debug!(" => associated item with unsizeable self: Self");
Some(Instance { def: InstanceDef::VtableShim(def_id), substs }) Some(Instance { def: InstanceDef::VtableShim(def_id), substs })
} else { } else {
Instance::resolve(tcx, param_env, def_id, substs) Instance::resolve(tcx, param_env, def_id, substs).ok().flatten()
} }
} }
@ -353,7 +366,7 @@ impl<'tcx> Instance<'tcx> {
pub fn resolve_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> { pub fn resolve_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> {
let def_id = tcx.require_lang_item(DropInPlaceFnLangItem, None); let def_id = tcx.require_lang_item(DropInPlaceFnLangItem, None);
let substs = tcx.intern_substs(&[ty.into()]); let substs = tcx.intern_substs(&[ty.into()]);
Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap() Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap().unwrap()
} }
pub fn fn_once_adapter_instance( pub fn fn_once_adapter_instance(

View File

@ -296,14 +296,3 @@ impl Key for (Symbol, u32, u32) {
DUMMY_SP DUMMY_SP
} }
} }
impl<'tcx> Key for (ty::ParamEnv<'tcx>, DefId, SubstsRef<'tcx>) {
type CacheSelector = DefaultCacheSelector;
fn query_crate(&self) -> CrateNum {
self.1.krate
}
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
tcx.def_span(self.1)
}
}

View File

@ -461,8 +461,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
trace!("resolve: {:?}, {:#?}", def_id, substs); trace!("resolve: {:?}, {:#?}", def_id, substs);
trace!("param_env: {:#?}", self.param_env); trace!("param_env: {:#?}", self.param_env);
trace!("substs: {:#?}", substs); trace!("substs: {:#?}", substs);
ty::Instance::resolve(*self.tcx, self.param_env, def_id, substs) match ty::Instance::resolve(*self.tcx, self.param_env, def_id, substs) {
.ok_or_else(|| err_inval!(TooGeneric).into()) Ok(Some(instance)) => Ok(instance),
Ok(None) => throw_inval!(TooGeneric),
// FIXME(eddyb) this could be a bit more specific than `TypeckError`.
Err(error_reported) => throw_inval!(TypeckError(error_reported)),
}
} }
pub fn layout_of_local( pub fn layout_of_local(

View File

@ -674,9 +674,12 @@ fn visit_fn_use<'tcx>(
output: &mut Vec<MonoItem<'tcx>>, output: &mut Vec<MonoItem<'tcx>>,
) { ) {
if let ty::FnDef(def_id, substs) = ty.kind { if let ty::FnDef(def_id, substs) = ty.kind {
let resolver = let instance = if is_direct_call {
if is_direct_call { ty::Instance::resolve } else { ty::Instance::resolve_for_fn_ptr }; ty::Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap().unwrap()
let instance = resolver(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap(); } else {
ty::Instance::resolve_for_fn_ptr(tcx, ty::ParamEnv::reveal_all(), def_id, substs)
.unwrap()
};
visit_instance_use(tcx, instance, is_direct_call, output); visit_instance_use(tcx, instance, is_direct_call, output);
} }
} }
@ -1056,6 +1059,7 @@ impl RootCollector<'_, 'v> {
start_def_id, start_def_id,
self.tcx.intern_substs(&[main_ret_ty.into()]), self.tcx.intern_substs(&[main_ret_ty.into()]),
) )
.unwrap()
.unwrap(); .unwrap();
self.output.push(create_fn_mono_item(start_instance)); self.output.push(create_fn_mono_item(start_instance));
@ -1111,8 +1115,9 @@ fn create_mono_items_for_default_impls<'tcx>(
trait_ref.substs[param.index as usize] trait_ref.substs[param.index as usize]
} }
}); });
let instance = let instance = ty::Instance::resolve(tcx, param_env, method.def_id, substs)
ty::Instance::resolve(tcx, param_env, method.def_id, substs).unwrap(); .unwrap()
.unwrap();
let mono_item = create_fn_mono_item(instance); let mono_item = create_fn_mono_item(instance);
if mono_item.is_instantiable(tcx) && should_monomorphize_locally(tcx, &instance) if mono_item.is_instantiable(tcx) && should_monomorphize_locally(tcx, &instance)

View File

@ -18,7 +18,7 @@ pub fn custom_coerce_unsize_info<'tcx>(
}); });
match tcx.codegen_fulfill_obligation((ty::ParamEnv::reveal_all(), trait_ref)) { match tcx.codegen_fulfill_obligation((ty::ParamEnv::reveal_all(), trait_ref)) {
Some(traits::VtableImpl(traits::VtableImplData { impl_def_id, .. })) => { Ok(traits::VtableImpl(traits::VtableImplData { impl_def_id, .. })) => {
tcx.coerce_unsized_info(impl_def_id).custom_kind.unwrap() tcx.coerce_unsized_info(impl_def_id).custom_kind.unwrap()
} }
vtable => { vtable => {

View File

@ -522,7 +522,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
if self.tcx.features().const_trait_impl { if self.tcx.features().const_trait_impl {
let instance = Instance::resolve(self.tcx, self.param_env, def_id, substs); let instance = Instance::resolve(self.tcx, self.param_env, def_id, substs);
debug!("Resolving ({:?}) -> {:?}", def_id, instance); debug!("Resolving ({:?}) -> {:?}", def_id, instance);
if let Some(func) = instance { if let Ok(Some(func)) = instance {
if let InstanceDef::Item(def_id) = func.def { if let InstanceDef::Item(def_id) = func.def {
if is_const_fn(self.tcx, def_id) { if is_const_fn(self.tcx, def_id) {
return; return;

View File

@ -176,7 +176,8 @@ impl Inliner<'tcx> {
let terminator = bb_data.terminator(); let terminator = bb_data.terminator();
if let TerminatorKind::Call { func: ref op, .. } = terminator.kind { if let TerminatorKind::Call { func: ref op, .. } = terminator.kind {
if let ty::FnDef(callee_def_id, substs) = op.ty(caller_body, self.tcx).kind { if let ty::FnDef(callee_def_id, substs) = op.ty(caller_body, self.tcx).kind {
let instance = Instance::resolve(self.tcx, param_env, callee_def_id, substs)?; let instance =
Instance::resolve(self.tcx, param_env, callee_def_id, substs).ok().flatten()?;
if let InstanceDef::Virtual(..) = instance.def { if let InstanceDef::Virtual(..) = instance.def {
return None; return None;

View File

@ -72,7 +72,7 @@ impl<'mir, 'tcx> Search<'mir, 'tcx> {
let func_ty = func.ty(body, tcx); let func_ty = func.ty(body, tcx);
if let ty::FnDef(fn_def_id, substs) = func_ty.kind { if let ty::FnDef(fn_def_id, substs) = func_ty.kind {
let (call_fn_id, call_substs) = let (call_fn_id, call_substs) =
if let Some(instance) = Instance::resolve(tcx, param_env, fn_def_id, substs) { if let Ok(Some(instance)) = Instance::resolve(tcx, param_env, fn_def_id, substs) {
(instance.def_id(), instance.substs) (instance.def_id(), instance.substs)
} else { } else {
(fn_def_id, substs) (fn_def_id, substs)

View File

@ -4,7 +4,7 @@ use rustc_ast::attr;
use rustc_ast::token::{self, Nonterminal}; use rustc_ast::token::{self, Nonterminal};
use rustc_ast::util::comments; use rustc_ast::util::comments;
use rustc_ast_pretty::pprust; use rustc_ast_pretty::pprust;
use rustc_errors::PResult; use rustc_errors::{error_code, PResult};
use rustc_span::{Span, Symbol}; use rustc_span::{Span, Symbol};
use log::debug; use log::debug;
@ -50,10 +50,16 @@ impl<'a> Parser<'a> {
} else if let token::DocComment(s) = self.token.kind { } else if let token::DocComment(s) = self.token.kind {
let attr = self.mk_doc_comment(s); let attr = self.mk_doc_comment(s);
if attr.style != ast::AttrStyle::Outer { if attr.style != ast::AttrStyle::Outer {
self.struct_span_err(self.token.span, "expected outer doc comment") self.sess
.span_diagnostic
.struct_span_err_with_code(
self.token.span,
"expected outer doc comment",
error_code!(E0753),
)
.note( .note(
"inner doc comments like this (starting with \ "inner doc comments like this (starting with \
`//!` or `/*!`) can only appear before items", `//!` or `/*!`) can only appear before items",
) )
.emit(); .emit();
} }

View File

@ -7,6 +7,7 @@ use crate::infer::{InferCtxt, TyCtxtInferExt};
use crate::traits::{ use crate::traits::{
FulfillmentContext, Obligation, ObligationCause, SelectionContext, TraitEngine, Vtable, FulfillmentContext, Obligation, ObligationCause, SelectionContext, TraitEngine, Vtable,
}; };
use rustc_errors::ErrorReported;
use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{self, TyCtxt};
@ -19,7 +20,7 @@ use rustc_middle::ty::{self, TyCtxt};
pub fn codegen_fulfill_obligation<'tcx>( pub fn codegen_fulfill_obligation<'tcx>(
ty: TyCtxt<'tcx>, ty: TyCtxt<'tcx>,
(param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>), (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>),
) -> Option<Vtable<'tcx, ()>> { ) -> Result<Vtable<'tcx, ()>, ErrorReported> {
// Remove any references to regions; this helps improve caching. // Remove any references to regions; this helps improve caching.
let trait_ref = ty.erase_regions(&trait_ref); let trait_ref = ty.erase_regions(&trait_ref);
@ -55,7 +56,7 @@ pub fn codegen_fulfill_obligation<'tcx>(
trait_ref trait_ref
), ),
); );
return None; return Err(ErrorReported);
} }
Err(e) => { Err(e) => {
bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref) bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref)
@ -75,7 +76,7 @@ pub fn codegen_fulfill_obligation<'tcx>(
let vtable = drain_fulfillment_cx_or_panic(&infcx, &mut fulfill_cx, &vtable); let vtable = drain_fulfillment_cx_or_panic(&infcx, &mut fulfill_cx, &vtable);
info!("Cache miss: {:?} => {:?}", trait_ref, vtable); info!("Cache miss: {:?} => {:?}", trait_ref, vtable);
Some(vtable) Ok(vtable)
}) })
} }

View File

@ -125,6 +125,7 @@ pub trait InferCtxtExt<'tcx> {
err: &mut DiagnosticBuilder<'_>, err: &mut DiagnosticBuilder<'_>,
target_span: Span, target_span: Span,
scope_span: &Option<Span>, scope_span: &Option<Span>,
await_span: Span,
expr: Option<hir::HirId>, expr: Option<hir::HirId>,
snippet: String, snippet: String,
inner_generator_body: Option<&hir::Body<'_>>, inner_generator_body: Option<&hir::Body<'_>>,
@ -1289,8 +1290,16 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
ty_matches(ty) ty_matches(ty)
}) })
.map(|expr| expr.span); .map(|expr| expr.span);
let ty::GeneratorInteriorTypeCause { span, scope_span, expr, .. } = cause; let ty::GeneratorInteriorTypeCause { span, scope_span, yield_span, expr, .. } =
(span, source_map.span_to_snippet(*span), scope_span, expr, from_awaited_ty) cause;
(
span,
source_map.span_to_snippet(*span),
scope_span,
yield_span,
expr,
from_awaited_ty,
)
}); });
debug!( debug!(
@ -1298,11 +1307,14 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
generator_interior_types={:?} target_span={:?}", generator_interior_types={:?} target_span={:?}",
target_ty, tables.generator_interior_types, target_span target_ty, tables.generator_interior_types, target_span
); );
if let Some((target_span, Ok(snippet), scope_span, expr, from_awaited_ty)) = target_span { if let Some((target_span, Ok(snippet), scope_span, yield_span, expr, from_awaited_ty)) =
target_span
{
self.note_obligation_cause_for_async_await( self.note_obligation_cause_for_async_await(
err, err,
*target_span, *target_span,
scope_span, scope_span,
*yield_span,
*expr, *expr,
snippet, snippet,
generator_body, generator_body,
@ -1327,6 +1339,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
err: &mut DiagnosticBuilder<'_>, err: &mut DiagnosticBuilder<'_>,
target_span: Span, target_span: Span,
scope_span: &Option<Span>, scope_span: &Option<Span>,
yield_span: Span,
expr: Option<hir::HirId>, expr: Option<hir::HirId>,
snippet: String, snippet: String,
inner_generator_body: Option<&hir::Body<'_>>, inner_generator_body: Option<&hir::Body<'_>>,
@ -1418,10 +1431,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
"note_obligation_cause_for_async_await generator_interior_types: {:#?}", "note_obligation_cause_for_async_await generator_interior_types: {:#?}",
tables.generator_interior_types tables.generator_interior_types
); );
let await_span = tables.generator_interior_types.iter().map(|t| t.span).last().unwrap(); let mut span = MultiSpan::from_span(yield_span);
let mut span = MultiSpan::from_span(await_span);
span.push_span_label( span.push_span_label(
await_span, yield_span,
format!("{} occurs here, with `{}` maybe used later", await_or_yield, snippet), format!("{} occurs here, with `{}` maybe used later", await_or_yield, snippet),
); );

View File

@ -12,6 +12,7 @@ path = "lib.rs"
log = "0.4" log = "0.4"
rustc_middle = { path = "../librustc_middle" } rustc_middle = { path = "../librustc_middle" }
rustc_data_structures = { path = "../librustc_data_structures" } rustc_data_structures = { path = "../librustc_data_structures" }
rustc_errors = { path = "../librustc_errors" }
rustc_hir = { path = "../librustc_hir" } rustc_hir = { path = "../librustc_hir" }
rustc_infer = { path = "../librustc_infer" } rustc_infer = { path = "../librustc_infer" }
rustc_span = { path = "../librustc_span" } rustc_span = { path = "../librustc_span" }

View File

@ -1,3 +1,4 @@
use rustc_errors::ErrorReported;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::subst::SubstsRef;
@ -9,10 +10,12 @@ use traits::{translate_substs, Reveal};
use log::debug; use log::debug;
pub fn resolve_instance<'tcx>( fn resolve_instance<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
(param_env, def_id, substs): (ty::ParamEnv<'tcx>, DefId, SubstsRef<'tcx>), key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>,
) -> Option<Instance<'tcx>> { ) -> Result<Option<Instance<'tcx>>, ErrorReported> {
let (param_env, (def_id, substs)) = key.into_parts();
debug!("resolve(def_id={:?}, substs={:?})", def_id, substs); debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
let result = if let Some(trait_def_id) = tcx.trait_of_item(def_id) { let result = if let Some(trait_def_id) = tcx.trait_of_item(def_id) {
debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env); debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env);
@ -38,7 +41,7 @@ pub fn resolve_instance<'tcx>(
if ty.needs_drop(tcx, param_env) { if ty.needs_drop(tcx, param_env) {
// `DropGlue` requires a monomorphic aka concrete type. // `DropGlue` requires a monomorphic aka concrete type.
if ty.needs_subst() { if ty.needs_subst() {
return None; return Ok(None);
} }
debug!(" => nontrivial drop glue"); debug!(" => nontrivial drop glue");
@ -53,7 +56,7 @@ pub fn resolve_instance<'tcx>(
ty::InstanceDef::Item(def_id) ty::InstanceDef::Item(def_id)
} }
}; };
Some(Instance { def, substs }) Ok(Some(Instance { def, substs }))
}; };
debug!("resolve(def_id={:?}, substs={:?}) = {:?}", def_id, substs, result); debug!("resolve(def_id={:?}, substs={:?}) = {:?}", def_id, substs, result);
result result
@ -65,7 +68,7 @@ fn resolve_associated_item<'tcx>(
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
trait_id: DefId, trait_id: DefId,
rcvr_substs: SubstsRef<'tcx>, rcvr_substs: SubstsRef<'tcx>,
) -> Option<Instance<'tcx>> { ) -> Result<Option<Instance<'tcx>>, ErrorReported> {
let def_id = trait_item.def_id; let def_id = trait_item.def_id;
debug!( debug!(
"resolve_associated_item(trait_item={:?}, \ "resolve_associated_item(trait_item={:?}, \
@ -80,7 +83,7 @@ fn resolve_associated_item<'tcx>(
// Now that we know which impl is being used, we can dispatch to // Now that we know which impl is being used, we can dispatch to
// the actual function: // the actual function:
match vtbl { Ok(match vtbl {
traits::VtableImpl(impl_data) => { traits::VtableImpl(impl_data) => {
debug!( debug!(
"resolving VtableImpl: {:?}, {:?}, {:?}, {:?}", "resolving VtableImpl: {:?}, {:?}, {:?}, {:?}",
@ -92,13 +95,11 @@ fn resolve_associated_item<'tcx>(
let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap(); let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap();
let trait_def = tcx.trait_def(trait_def_id); let trait_def = tcx.trait_def(trait_def_id);
let leaf_def = trait_def let leaf_def = trait_def
.ancestors(tcx, impl_data.impl_def_id) .ancestors(tcx, impl_data.impl_def_id)?
.ok()?
.leaf_def(tcx, trait_item.ident, trait_item.kind) .leaf_def(tcx, trait_item.ident, trait_item.kind)
.unwrap_or_else(|| { .unwrap_or_else(|| {
bug!("{:?} not found in {:?}", trait_item, impl_data.impl_def_id); bug!("{:?} not found in {:?}", trait_item, impl_data.impl_def_id);
}); });
let def_id = leaf_def.item.def_id;
let substs = tcx.infer_ctxt().enter(|infcx| { let substs = tcx.infer_ctxt().enter(|infcx| {
let param_env = param_env.with_reveal_all(); let param_env = param_env.with_reveal_all();
@ -133,11 +134,52 @@ fn resolve_associated_item<'tcx>(
}; };
if !eligible { if !eligible {
return None; return Ok(None);
} }
let substs = tcx.erase_regions(&substs); let substs = tcx.erase_regions(&substs);
Some(ty::Instance::new(def_id, substs))
// Check if we just resolved an associated `const` declaration from
// a `trait` to an associated `const` definition in an `impl`, where
// the definition in the `impl` has the wrong type (for which an
// error has already been/will be emitted elsewhere).
//
// NB: this may be expensive, we try to skip it in all the cases where
// we know the error would've been caught (e.g. in an upstream crate).
//
// A better approach might be to just introduce a query (returning
// `Result<(), ErrorReported>`) for the check that `rustc_typeck`
// performs (i.e. that the definition's type in the `impl` matches
// the declaration in the `trait`), so that we can cheaply check
// here if it failed, instead of approximating it.
if trait_item.kind == ty::AssocKind::Const
&& trait_item.def_id != leaf_def.item.def_id
&& leaf_def.item.def_id.is_local()
{
let normalized_type_of = |def_id, substs| {
tcx.subst_and_normalize_erasing_regions(substs, param_env, &tcx.type_of(def_id))
};
let original_ty = normalized_type_of(trait_item.def_id, rcvr_substs);
let resolved_ty = normalized_type_of(leaf_def.item.def_id, substs);
if original_ty != resolved_ty {
let msg = format!(
"Instance::resolve: inconsistent associated `const` type: \
was `{}: {}` but resolved to `{}: {}`",
tcx.def_path_str_with_substs(trait_item.def_id, rcvr_substs),
original_ty,
tcx.def_path_str_with_substs(leaf_def.item.def_id, substs),
resolved_ty,
);
let span = tcx.def_span(leaf_def.item.def_id);
tcx.sess.delay_span_bug(span, &msg);
return Err(ErrorReported);
}
}
Some(ty::Instance::new(leaf_def.item.def_id, substs))
} }
traits::VtableGenerator(generator_data) => Some(Instance { traits::VtableGenerator(generator_data) => Some(Instance {
def: ty::InstanceDef::Item(generator_data.generator_def_id), def: ty::InstanceDef::Item(generator_data.generator_def_id),
@ -155,7 +197,7 @@ fn resolve_associated_item<'tcx>(
traits::VtableFnPointer(ref data) => { traits::VtableFnPointer(ref data) => {
// `FnPtrShim` requires a monomorphic aka concrete type. // `FnPtrShim` requires a monomorphic aka concrete type.
if data.fn_ty.needs_subst() { if data.fn_ty.needs_subst() {
return None; return Ok(None);
} }
Some(Instance { Some(Instance {
@ -176,7 +218,7 @@ fn resolve_associated_item<'tcx>(
// `CloneShim` requires a monomorphic aka concrete type. // `CloneShim` requires a monomorphic aka concrete type.
if self_ty.needs_subst() { if self_ty.needs_subst() {
return None; return Ok(None);
} }
Some(Instance { Some(Instance {
@ -195,7 +237,7 @@ fn resolve_associated_item<'tcx>(
} }
} }
traits::VtableAutoImpl(..) | traits::VtableParam(..) | traits::VtableTraitAlias(..) => None, traits::VtableAutoImpl(..) | traits::VtableParam(..) | traits::VtableTraitAlias(..) => None,
} })
} }
pub fn provide(providers: &mut ty::query::Providers<'_>) { pub fn provide(providers: &mut ty::query::Providers<'_>) {

View File

@ -96,6 +96,7 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
span: source_span, span: source_span,
ty: &ty, ty: &ty,
scope_span, scope_span,
yield_span: yield_data.span,
expr: expr.map(|e| e.hir_id), expr: expr.map(|e| e.hir_id),
}) })
.or_insert(entries); .or_insert(entries);

View File

@ -198,6 +198,7 @@ use crate::sys;
/// ``` /// ```
#[derive(Clone)] #[derive(Clone)]
#[cfg_attr(not(test), rustc_diagnostic_item = "hashmap_type")]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct HashMap<K, V, S = RandomState> { pub struct HashMap<K, V, S = RandomState> {
base: base::HashMap<K, V, S>, base: base::HashMap<K, V, S>,

View File

@ -105,6 +105,7 @@ use super::map::{self, HashMap, Keys, RandomState};
/// [`PartialEq`]: ../../std/cmp/trait.PartialEq.html /// [`PartialEq`]: ../../std/cmp/trait.PartialEq.html
/// [`RefCell`]: ../../std/cell/struct.RefCell.html /// [`RefCell`]: ../../std/cell/struct.RefCell.html
#[derive(Clone)] #[derive(Clone)]
#[cfg_attr(not(test), rustc_diagnostic_item = "hashset_type")]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct HashSet<T, S = RandomState> { pub struct HashSet<T, S = RandomState> {
map: HashMap<T, (), S>, map: HashMap<T, (), S>,

View File

@ -108,6 +108,7 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult};
/// *guard += 1; /// *guard += 1;
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "mutex_type")]
pub struct Mutex<T: ?Sized> { pub struct Mutex<T: ?Sized> {
// Note that this mutex is in a *box*, not inlined into the struct itself. // Note that this mutex is in a *box*, not inlined into the struct itself.
// Once a native mutex has been used once, its address can never change (it // Once a native mutex has been used once, its address can never change (it

View File

@ -1,4 +1,4 @@
// build-pass (FIXME(62277): could be check-pass?) // check-pass
// compile-flags:--test --test-args --test-threads=1 // compile-flags:--test --test-args --test-threads=1
// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR" // normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"

View File

@ -1,5 +1,5 @@
// compile-flags:-Z unstable-options --show-coverage // compile-flags:-Z unstable-options --show-coverage
// build-pass (FIXME(62277): could be check-pass?) // check-pass
#![feature(extern_types)] #![feature(extern_types)]

View File

@ -1,4 +1,4 @@
// compile-flags:-Z unstable-options --show-coverage // compile-flags:-Z unstable-options --show-coverage
// build-pass (FIXME(62277): could be check-pass?) // check-pass
// an empty crate still has one item to document: the crate root // an empty crate still has one item to document: the crate root

View File

@ -1,5 +1,5 @@
// compile-flags:-Z unstable-options --show-coverage // compile-flags:-Z unstable-options --show-coverage
// build-pass (FIXME(62277): could be check-pass?) // check-pass
//! (remember the crate root is still a module) //! (remember the crate root is still a module)

View File

@ -1,5 +1,5 @@
// compile-flags:-Z unstable-options --show-coverage // compile-flags:-Z unstable-options --show-coverage
// build-pass (FIXME(62277): could be check-pass?) // check-pass
#![feature(doc_keyword)] #![feature(doc_keyword)]

View File

@ -1,4 +1,4 @@
// build-pass // check-pass
// compile-flags:-Z unstable-options --output-format json --show-coverage // compile-flags:-Z unstable-options --output-format json --show-coverage
pub mod foo { pub mod foo {

View File

@ -1,5 +1,5 @@
// compile-flags:-Z unstable-options --show-coverage --document-private-items // compile-flags:-Z unstable-options --show-coverage --document-private-items
// build-pass (FIXME(62277): could be check-pass?) // check-pass
#![allow(unused)] #![allow(unused)]

View File

@ -1,5 +1,5 @@
// compile-flags:-Z unstable-options --show-coverage // compile-flags:-Z unstable-options --show-coverage
// build-pass (FIXME(62277): could be check-pass?) // check-pass
//! gotta make sure we can count statics and consts correctly, too //! gotta make sure we can count statics and consts correctly, too

View File

@ -1,5 +1,5 @@
// compile-flags:-Z unstable-options --show-coverage // compile-flags:-Z unstable-options --show-coverage
// build-pass (FIXME(62277): could be check-pass?) // check-pass
#![feature(trait_alias)] #![feature(trait_alias)]

View File

@ -1,4 +1,4 @@
// build-pass (FIXME(62277): could be check-pass?) // check-pass
#![doc(no_default_passes, passes = "collapse-docs unindent-comments")] #![doc(no_default_passes, passes = "collapse-docs unindent-comments")]

View File

@ -1,4 +1,4 @@
// build-pass // check-pass
// compile-flags:--test // compile-flags:--test
// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR" // normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"

View File

@ -1,4 +1,4 @@
// build-pass // check-pass
// compile-flags:--test // compile-flags:--test
// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR" // normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"

View File

@ -1,5 +1,5 @@
// ignore-tidy-cr // ignore-tidy-cr
// build-pass // check-pass
// This file checks the spans of intra-link warnings in a file with CRLF line endings. The // This file checks the spans of intra-link warnings in a file with CRLF line endings. The
// .gitattributes file in this directory should enforce it. // .gitattributes file in this directory should enforce it.

View File

@ -1,4 +1,4 @@
// build-pass // check-pass
//! Test with [Foo::baz], [Bar::foo], ... //! Test with [Foo::baz], [Bar::foo], ...
//~^ WARNING `[Foo::baz]` cannot be resolved //~^ WARNING `[Foo::baz]` cannot be resolved

View File

@ -1,4 +1,4 @@
// build-pass // check-pass
/// ``` /// ```
/// \__________pkt->size___________/ \_result->size_/ \__pkt->size__/ /// \__________pkt->size___________/ \_result->size_/ \__pkt->size__/

View File

@ -1,4 +1,4 @@
// build-pass (FIXME(62277): could be check-pass?) // check-pass
#![deny(private_doc_tests)] #![deny(private_doc_tests)]

View File

@ -1,4 +1,4 @@
// build-pass (FIXME(62277): could be check-pass?) // check-pass
pub trait Foo { pub trait Foo {
/** /**

View File

@ -1,6 +1,6 @@
// compile-flags:--test // compile-flags:--test
// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR" // normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
// build-pass // check-pass
#![no_std] #![no_std]

View File

@ -1,4 +1,4 @@
// build-pass (FIXME(62277): could be check-pass?) // check-pass
// This test purpose is to check that unused_imports lint isn't fired // This test purpose is to check that unused_imports lint isn't fired
// by rustdoc. Why would it? Because when rustdoc is running, it uses // by rustdoc. Why would it? Because when rustdoc is running, it uses

View File

@ -0,0 +1,21 @@
// edition:2018
use std::future::Future;
use std::sync::Mutex;
fn fake_spawn<F: Future + Send + 'static>(f: F) { }
async fn wrong_mutex() {
let m = Mutex::new(1);
{
let mut guard = m.lock().unwrap();
(async { "right"; }).await;
*guard += 1;
}
(async { "wrong"; }).await;
}
fn main() {
fake_spawn(wrong_mutex()); //~ Error future cannot be sent between threads safely
}

View File

@ -0,0 +1,23 @@
error: future cannot be sent between threads safely
--> $DIR/issue-71137.rs:20:3
|
LL | fn fake_spawn<F: Future + Send + 'static>(f: F) { }
| ---- required by this bound in `fake_spawn`
...
LL | fake_spawn(wrong_mutex());
| ^^^^^^^^^^ future returned by `wrong_mutex` is not `Send`
|
= help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::sync::MutexGuard<'_, i32>`
note: future is not `Send` as this value is used across an await
--> $DIR/issue-71137.rs:12:5
|
LL | let mut guard = m.lock().unwrap();
| --------- has type `std::sync::MutexGuard<'_, i32>` which is not `Send`
LL | (async { "right"; }).await;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ await occurs here, with `mut guard` maybe used later
LL | *guard += 1;
LL | }
| - `mut guard` is later dropped here
error: aborting due to previous error

View File

@ -0,0 +1,14 @@
trait Nat {
const VALUE: usize;
}
struct Zero;
impl Nat for Zero {
const VALUE: i32 = 0;
//~^ ERROR implemented const `VALUE` has an incompatible type for trait
}
fn main() {
let _: [i32; Zero::VALUE] = [];
}

View File

@ -0,0 +1,12 @@
error[E0326]: implemented const `VALUE` has an incompatible type for trait
--> $DIR/issue-70942-trait-vs-impl-mismatch.rs:8:18
|
LL | const VALUE: usize;
| ----- type in trait
...
LL | const VALUE: i32 = 0;
| ^^^ expected `usize`, found `i32`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0326`.

View File

@ -19,5 +19,4 @@ impl TraitB for B { //~ ERROR not all trait items implemented, missing: `MyA`
fn main() { fn main() {
let _ = [0; B::VALUE]; let _ = [0; B::VALUE];
//~^ ERROR constant expression depends on a generic parameter
} }

View File

@ -13,15 +13,7 @@ LL | type MyA: TraitA;
LL | impl TraitB for B { LL | impl TraitB for B {
| ^^^^^^^^^^^^^^^^^ missing `MyA` in implementation | ^^^^^^^^^^^^^^^^^ missing `MyA` in implementation
error: constant expression depends on a generic parameter error: aborting due to 2 previous errors
--> $DIR/issue-69602-type-err-during-codegen-ice.rs:21:17
|
LL | let _ = [0; B::VALUE];
| ^^^^^^^^
|
= note: this may fail depending on what value the parameter takes
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0046, E0437. Some errors have detailed explanations: E0046, E0437.
For more information about an error, try `rustc --explain E0046`. For more information about an error, try `rustc --explain E0046`.

View File

@ -1,4 +1,4 @@
error: expected outer doc comment error[E0753]: expected outer doc comment
--> $DIR/doc-comment-in-if-statement.rs:2:13 --> $DIR/doc-comment-in-if-statement.rs:2:13
| |
LL | if true /*!*/ {} LL | if true /*!*/ {}
@ -17,3 +17,4 @@ LL | if true /*!*/ {}
error: aborting due to 2 previous errors error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0753`.

View File

@ -1,4 +1,4 @@
error: expected outer doc comment error[E0753]: expected outer doc comment
--> $DIR/issue-30318.rs:3:1 --> $DIR/issue-30318.rs:3:1
| |
LL | //! Misplaced comment... LL | //! Misplaced comment...
@ -8,3 +8,4 @@ LL | //! Misplaced comment...
error: aborting due to previous error error: aborting due to previous error
For more information about this error, try `rustc --explain E0753`.

View File

@ -2,7 +2,7 @@ error: unused doc comment
--> $DIR/useless-comment.rs:9:1 --> $DIR/useless-comment.rs:9:1
| |
LL | /// foo LL | /// foo
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ rustdoc does not generate documentation for macros | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ rustdoc does not generate documentation for macro invocations
| |
note: the lint level is defined here note: the lint level is defined here
--> $DIR/useless-comment.rs:3:9 --> $DIR/useless-comment.rs:3:9
@ -15,7 +15,7 @@ error: unused doc comment
--> $DIR/useless-comment.rs:32:5 --> $DIR/useless-comment.rs:32:5
| |
LL | /// bar LL | /// bar
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ rustdoc does not generate documentation for macros | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ rustdoc does not generate documentation for macro invocations
| |
= help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion