Skip to content

Commit

Permalink
Auto merge of rust-lang#78028 - JohnTitor:rollup-jt3hikb, r=JohnTitor
Browse files Browse the repository at this point in the history
Rollup of 10 pull requests

Successful merges:

 - rust-lang#75209 (Suggest imports of unresolved macros)
 - rust-lang#77547 (stabilize union with 'ManuallyDrop' fields and 'impl Drop for Union')
 - rust-lang#77827 (Don't link to nightly primitives on stable channel)
 - rust-lang#77855 (resolve: further improvements to "try using the enum's variant" diagnostic)
 - rust-lang#77900 (Use fdatasync for File::sync_data on more OSes)
 - rust-lang#77925 (Suggest minimal subset features in `incomplete_features` lint)
 - rust-lang#77971 (Deny broken intra-doc links in linkchecker)
 - rust-lang#77991 (Bump backtrace-rs)
 - rust-lang#77992 (instrument-coverage: try our best to not ICE)
 - rust-lang#78013 (Fix sidebar scroll on mobile devices)

Failed merges:

r? `@ghost`
  • Loading branch information
bors committed Oct 16, 2020
2 parents 5a51185 + 001fcd9 commit e3051d8
Show file tree
Hide file tree
Showing 154 changed files with 667 additions and 275 deletions.
4 changes: 4 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1744,6 +1744,10 @@ dependencies = [
[[package]]
name = "linkchecker"
version = "0.1.0"
dependencies = [
"once_cell",
"regex",
]

[[package]]
name = "linked-hash-map"
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_error_codes/src/error_codes/E0660.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ llvm_asm!("nop" "nop");
Considering that this would be a long explanation, we instead recommend you
take a look at the [`llvm_asm`] chapter of the Unstable book:

[llvm_asm]: https://doc.rust-lang.org/stable/unstable-book/library-features/llvm-asm.html
[`llvm_asm`]: https://doc.rust-lang.org/stable/unstable-book/library-features/llvm-asm.html
2 changes: 1 addition & 1 deletion compiler/rustc_error_codes/src/error_codes/E0661.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ llvm_asm!("nop" : "r"(a));
Considering that this would be a long explanation, we instead recommend you
take a look at the [`llvm_asm`] chapter of the Unstable book:

[llvm_asm]: https://doc.rust-lang.org/stable/unstable-book/library-features/llvm-asm.html
[`llvm_asm`]: https://doc.rust-lang.org/stable/unstable-book/library-features/llvm-asm.html
2 changes: 1 addition & 1 deletion compiler/rustc_error_codes/src/error_codes/E0662.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ llvm_asm!("xor %eax, %eax"
Considering that this would be a long explanation, we instead recommend you
take a look at the [`llvm_asm`] chapter of the Unstable book:

[llvm_asm]: https://doc.rust-lang.org/stable/unstable-book/library-features/llvm-asm.html
[`llvm_asm`]: https://doc.rust-lang.org/stable/unstable-book/library-features/llvm-asm.html
2 changes: 1 addition & 1 deletion compiler/rustc_error_codes/src/error_codes/E0663.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ llvm_asm!("xor %eax, %eax"
Considering that this would be a long explanation, we instead recommend you
take a look at the [`llvm_asm`] chapter of the Unstable book:

[llvm_asm]: https://doc.rust-lang.org/stable/unstable-book/library-features/llvm-asm.html
[`llvm_asm`]: https://doc.rust-lang.org/stable/unstable-book/library-features/llvm-asm.html
2 changes: 1 addition & 1 deletion compiler/rustc_error_codes/src/error_codes/E0664.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ llvm_asm!("mov $$0x200, %eax"
Considering that this would be a long explanation, we instead recommend you
take a look at the [`llvm_asm`] chapter of the Unstable book:

[llvm_asm]: https://doc.rust-lang.org/stable/unstable-book/library-features/llvm-asm.html
[`llvm_asm`]: https://doc.rust-lang.org/stable/unstable-book/library-features/llvm-asm.html
8 changes: 8 additions & 0 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2288,12 +2288,20 @@ impl EarlyLintPass for IncompleteFeatures {
n, n,
));
}
if HAS_MIN_FEATURES.contains(&name) {
builder.help(&format!(
"consider using `min_{}` instead, which is more stable and complete",
name,
));
}
builder.emit();
})
});
}
}

const HAS_MIN_FEATURES: &[Symbol] = &[sym::const_generics, sym::specialization];

declare_lint! {
/// The `invalid_value` lint detects creating a value that is not valid,
/// such as a NULL reference.
Expand Down
12 changes: 2 additions & 10 deletions compiler/rustc_mir/src/transform/instrument_coverage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_span::def_id::DefId;
use rustc_span::source_map::original_sp;
use rustc_span::{
BytePos, CharPos, FileName, Pos, RealFileName, SourceFile, Span, Symbol, SyntaxContext,
};
use rustc_span::{BytePos, CharPos, Pos, SourceFile, Span, Symbol, SyntaxContext};

use std::cmp::Ordering;

Expand Down Expand Up @@ -549,13 +547,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
let mir_body = &self.mir_body;
let body_span = self.body_span();
let source_file = source_map.lookup_source_file(body_span.lo());
let file_name = match &source_file.name {
FileName::Real(RealFileName::Named(path)) => Symbol::intern(&path.to_string_lossy()),
_ => bug!(
"source_file.name should be a RealFileName, but it was: {:?}",
source_file.name
),
};
let file_name = Symbol::intern(&source_file.name.to_string());

debug!("instrumenting {:?}, span: {}", def_id, source_map.span_to_string(body_span));

Expand Down
52 changes: 29 additions & 23 deletions compiler/rustc_passes/src/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,13 @@ use rustc_hir::{Generics, HirId, Item, StructField, TraitRef, Ty, TyKind, Varian
use rustc_middle::hir::map::Map;
use rustc_middle::middle::privacy::AccessLevels;
use rustc_middle::middle::stability::{DeprecationEntry, Index};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_middle::ty::{self, query::Providers, TyCtxt};
use rustc_session::lint;
use rustc_session::lint::builtin::INEFFECTIVE_UNSTABLE_TRAIT_IMPL;
use rustc_session::parse::feature_err;
use rustc_session::Session;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span;
use rustc_trait_selection::traits::misc::can_type_implement_copy;
use rustc_span::{Span, DUMMY_SP};

use std::cmp::Ordering;
use std::mem::replace;
Expand Down Expand Up @@ -711,27 +709,35 @@ impl Visitor<'tcx> for Checker<'tcx> {
// so semi-randomly perform it here in stability.rs
hir::ItemKind::Union(..) if !self.tcx.features().untagged_unions => {
let def_id = self.tcx.hir().local_def_id(item.hir_id);
let adt_def = self.tcx.adt_def(def_id);
let ty = self.tcx.type_of(def_id);
let (adt_def, substs) = match ty.kind() {
ty::Adt(adt_def, substs) => (adt_def, substs),
_ => bug!(),
};

if adt_def.has_dtor(self.tcx) {
feature_err(
&self.tcx.sess.parse_sess,
sym::untagged_unions,
item.span,
"unions with `Drop` implementations are unstable",
)
.emit();
} else {
let param_env = self.tcx.param_env(def_id);
if can_type_implement_copy(self.tcx, param_env, ty).is_err() {
feature_err(
&self.tcx.sess.parse_sess,
sym::untagged_unions,
item.span,
"unions with non-`Copy` fields are unstable",
)
.emit();
// Non-`Copy` fields are unstable, except for `ManuallyDrop`.
let param_env = self.tcx.param_env(def_id);
for field in &adt_def.non_enum_variant().fields {
let field_ty = field.ty(self.tcx, substs);
if !field_ty.ty_adt_def().map_or(false, |adt_def| adt_def.is_manually_drop())
&& !field_ty.is_copy_modulo_regions(self.tcx.at(DUMMY_SP), param_env)
{
if field_ty.needs_drop(self.tcx, param_env) {
// Avoid duplicate error: This will error later anyway because fields
// that need drop are not allowed.
self.tcx.sess.delay_span_bug(
item.span,
"union should have been rejected due to potentially dropping field",
);
} else {
feature_err(
&self.tcx.sess.parse_sess,
sym::untagged_unions,
self.tcx.def_span(field.did),
"unions with non-`Copy` fields other than `ManuallyDrop<T>` are unstable",
)
.emit();
}
}
}
}
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -922,6 +922,17 @@ impl<'a> Resolver<'a> {
);
self.add_typo_suggestion(err, suggestion, ident.span);

let import_suggestions = self.lookup_import_candidates(
ident,
Namespace::MacroNS,
parent_scope,
|res| match res {
Res::Def(DefKind::Macro(MacroKind::Bang), _) => true,
_ => false,
},
);
show_candidates(err, None, &import_suggestions, false, true);

if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) {
let msg = format!("unsafe traits like `{}` should be implemented explicitly", ident);
err.span_note(ident.span, &msg);
Expand Down
150 changes: 88 additions & 62 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1330,58 +1330,17 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {

let suggest_only_tuple_variants =
matches!(source, PathSource::TupleStruct(..)) || source.is_call();
let mut suggestable_variants = if suggest_only_tuple_variants {
if suggest_only_tuple_variants {
// Suggest only tuple variants regardless of whether they have fields and do not
// suggest path with added parenthesis.
variants
let mut suggestable_variants = variants
.iter()
.filter(|(.., kind)| *kind == CtorKind::Fn)
.map(|(variant, ..)| path_names_to_string(variant))
.collect::<Vec<_>>()
} else {
variants
.iter()
.filter(|(_, def_id, kind)| {
// Suggest only variants that have no fields (these can definitely
// be constructed).
let has_fields =
self.r.field_names.get(&def_id).map(|f| f.is_empty()).unwrap_or(false);
match kind {
CtorKind::Const => true,
CtorKind::Fn | CtorKind::Fictive if has_fields => true,
_ => false,
}
})
.map(|(variant, _, kind)| (path_names_to_string(variant), kind))
.map(|(variant_str, kind)| {
// Add constructor syntax where appropriate.
match kind {
CtorKind::Const => variant_str,
CtorKind::Fn => format!("({}())", variant_str),
CtorKind::Fictive => format!("({} {{}})", variant_str),
}
})
.collect::<Vec<_>>()
};

let non_suggestable_variant_count = variants.len() - suggestable_variants.len();
.collect::<Vec<_>>();

if !suggestable_variants.is_empty() {
let msg = if non_suggestable_variant_count == 0 && suggestable_variants.len() == 1 {
"try using the enum's variant"
} else {
"try using one of the enum's variants"
};
let non_suggestable_variant_count = variants.len() - suggestable_variants.len();

err.span_suggestions(
span,
msg,
suggestable_variants.drain(..),
Applicability::MaybeIncorrect,
);
}

if suggest_only_tuple_variants {
let source_msg = if source.is_call() {
"to construct"
} else if matches!(source, PathSource::TupleStruct(..)) {
Expand All @@ -1390,6 +1349,21 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
unreachable!()
};

if !suggestable_variants.is_empty() {
let msg = if non_suggestable_variant_count == 0 && suggestable_variants.len() == 1 {
format!("try {} the enum's variant", source_msg)
} else {
format!("try {} one of the enum's variants", source_msg)
};

err.span_suggestions(
span,
&msg,
suggestable_variants.drain(..),
Applicability::MaybeIncorrect,
);
}

// If the enum has no tuple variants..
if non_suggestable_variant_count == variants.len() {
err.help(&format!("the enum has no tuple variants {}", source_msg));
Expand All @@ -1408,24 +1382,76 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
));
}
} else {
let made_suggestion = non_suggestable_variant_count != variants.len();
if made_suggestion {
if non_suggestable_variant_count == 1 {
err.help(
"you might have meant to use the enum's other variant that has fields",
);
} else if non_suggestable_variant_count >= 1 {
err.help(
"you might have meant to use one of the enum's other variants that \
have fields",
);
}
} else {
if non_suggestable_variant_count == 1 {
err.help("you might have meant to use the enum's variant");
} else if non_suggestable_variant_count >= 1 {
err.help("you might have meant to use one of the enum's variants");
let needs_placeholder = |def_id: DefId, kind: CtorKind| {
let has_no_fields =
self.r.field_names.get(&def_id).map(|f| f.is_empty()).unwrap_or(false);
match kind {
CtorKind::Const => false,
CtorKind::Fn | CtorKind::Fictive if has_no_fields => false,
_ => true,
}
};

let mut suggestable_variants = variants
.iter()
.filter(|(_, def_id, kind)| !needs_placeholder(*def_id, *kind))
.map(|(variant, _, kind)| (path_names_to_string(variant), kind))
.map(|(variant, kind)| match kind {
CtorKind::Const => variant,
CtorKind::Fn => format!("({}())", variant),
CtorKind::Fictive => format!("({} {{}})", variant),
})
.collect::<Vec<_>>();

if !suggestable_variants.is_empty() {
let msg = if suggestable_variants.len() == 1 {
"you might have meant to use the following enum variant"
} else {
"you might have meant to use one of the following enum variants"
};

err.span_suggestions(
span,
msg,
suggestable_variants.drain(..),
Applicability::MaybeIncorrect,
);
}

let mut suggestable_variants_with_placeholders = variants
.iter()
.filter(|(_, def_id, kind)| needs_placeholder(*def_id, *kind))
.map(|(variant, _, kind)| (path_names_to_string(variant), kind))
.filter_map(|(variant, kind)| match kind {
CtorKind::Fn => Some(format!("({}(/* fields */))", variant)),
CtorKind::Fictive => Some(format!("({} {{ /* fields */ }})", variant)),
_ => None,
})
.collect::<Vec<_>>();

if !suggestable_variants_with_placeholders.is_empty() {
let msg = match (
suggestable_variants.is_empty(),
suggestable_variants_with_placeholders.len(),
) {
(true, 1) => "the following enum variant is available",
(true, _) => "the following enum variants are available",
(false, 1) => "alternatively, the following enum variant is available",
(false, _) => "alternatively, the following enum variants are also available",
};

err.span_suggestions(
span,
msg,
suggestable_variants_with_placeholders.drain(..),
Applicability::HasPlaceholders,
);
}
};

if def_id.is_local() {
if let Some(span) = self.def_span(def_id) {
err.span_note(span, "the enum is defined here");
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_typeck/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,7 @@ pub(super) fn check_union(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) {
check_packed(tcx, span, def);
}

/// When the `#![feature(untagged_unions)]` gate is active,
/// check that the fields of the `union` does not contain fields that need dropping.
/// Check that the fields of the `union` do not need dropping.
pub(super) fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> bool {
let item_type = tcx.type_of(item_def_id);
if let ty::Adt(def, substs) = item_type.kind() {
Expand Down
Loading

0 comments on commit e3051d8

Please sign in to comment.