Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 7 pull requests #100449

Closed
wants to merge 19 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
127b6c4
cleanup code w/ pointers in std a little
WaffleLapkin Aug 1, 2022
a7c45ec
improve documentation of `pointer::align_offset`
WaffleLapkin Aug 1, 2022
cc8259e
Adding more verbose documentation for `std::fmt::Write`
thedanvail Aug 8, 2022
d52ed82
move an `assert!` to the right place
WaffleLapkin Aug 9, 2022
0436067
Merge branch 'rust-lang:master' into issue-98861-fix
thedanvail Aug 9, 2022
ee8a01f
Switching documentation to be more clear about potential errors
thedanvail Aug 9, 2022
2eebd34
errors: don't fail on broken primary translations
davidtwco Aug 10, 2022
e1e25a8
Generalize trait object generic param check to aliases.
cjgillot Aug 7, 2022
0df84ae
Ban indirect references to `Self` too.
cjgillot Aug 7, 2022
98518c2
suggest const or static for global variable
chenyukang Aug 11, 2022
dd4613c
rustdoc: don't generate DOM element for operator
jsha Aug 11, 2022
f5765ae
make clean::Item::span return option instead of dummy span
compiler-errors Aug 9, 2022
5272810
Rollup merge of #100030 - WaffleLapkin:nice_pointer_sis, r=scottmcm
Dylan-DPC Aug 12, 2022
511eda1
Rollup merge of #100247 - cjgillot:verify-dyn-trait-alias-defaults, r…
Dylan-DPC Aug 12, 2022
dbea6ac
Rollup merge of #100255 - thedanvail:issue-98861-fix, r=joshtriplett
Dylan-DPC Aug 12, 2022
f3e083a
Rollup merge of #100299 - compiler-errors:issue-100283, r=notriddle
Dylan-DPC Aug 12, 2022
aa2b716
Rollup merge of #100366 - davidtwco:translation-never-fail, r=compile…
Dylan-DPC Aug 12, 2022
e9fbfa2
Rollup merge of #100396 - chenyukang:fix-100394, r=petrochenkov
Dylan-DPC Aug 12, 2022
5a9a84f
Rollup merge of #100409 - jsha:highlight-lighter, r=GuillaumeGomez
Dylan-DPC Aug 12, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 49 additions & 31 deletions compiler/rustc_errors/src/emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,40 +273,58 @@ pub trait Emitter {
DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr),
};

let bundle = match self.fluent_bundle() {
Some(bundle) if bundle.has_message(&identifier) => bundle,
_ => self.fallback_fluent_bundle(),
};
let translate_with_bundle = |bundle: &'a FluentBundle| -> Option<(Cow<'_, str>, Vec<_>)> {
let message = bundle.get_message(&identifier)?;
let value = match attr {
Some(attr) => message.get_attribute(attr)?.value(),
None => message.value()?,
};
debug!(?message, ?value);

let message = bundle.get_message(&identifier).expect("missing diagnostic in fluent bundle");
let value = match attr {
Some(attr) => {
if let Some(attr) = message.get_attribute(attr) {
attr.value()
} else {
panic!("missing attribute `{attr}` in fluent message `{identifier}`")
}
}
None => {
if let Some(value) = message.value() {
value
} else {
panic!("missing value in fluent message `{identifier}`")
}
}
let mut errs = vec![];
let translated = bundle.format_pattern(value, Some(&args), &mut errs);
debug!(?translated, ?errs);
Some((translated, errs))
};

let mut err = vec![];
let translated = bundle.format_pattern(value, Some(&args), &mut err);
trace!(?translated, ?err);
debug_assert!(
err.is_empty(),
"identifier: {:?}, args: {:?}, errors: {:?}",
identifier,
args,
err
);
translated
self.fluent_bundle()
.and_then(|bundle| translate_with_bundle(bundle))
// If `translate_with_bundle` returns `None` with the primary bundle, this is likely
// just that the primary bundle doesn't contain the message being translated, so
// proceed to the fallback bundle.
//
// However, when errors are produced from translation, then that means the translation
// is broken (e.g. `{$foo}` exists in a translation but `foo` isn't provided).
//
// In debug builds, assert so that compiler devs can spot the broken translation and
// fix it..
.inspect(|(_, errs)| {
debug_assert!(
errs.is_empty(),
"identifier: {:?}, attr: {:?}, args: {:?}, errors: {:?}",
identifier,
attr,
args,
errs
);
})
// ..otherwise, for end users, an error about this wouldn't be useful or actionable, so
// just hide it and try with the fallback bundle.
.filter(|(_, errs)| errs.is_empty())
.or_else(|| translate_with_bundle(self.fallback_fluent_bundle()))
.map(|(translated, errs)| {
// Always bail out for errors with the fallback bundle.
assert!(
errs.is_empty(),
"identifier: {:?}, attr: {:?}, args: {:?}, errors: {:?}",
identifier,
attr,
args,
errs
);
translated
})
.expect("failed to find message in primary or fallback fluent bundles")
}

/// Formats the substitutions of the primary_span
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
#![feature(drain_filter)]
#![feature(if_let_guard)]
#![cfg_attr(bootstrap, feature(let_chains))]
#![feature(adt_const_params)]
#![feature(let_else)]
#![feature(never_type)]
#![feature(adt_const_params)]
#![feature(result_option_inspect)]
#![feature(rustc_attrs)]
#![allow(incomplete_features)]
#![allow(rustc::potential_query_instability)]
Expand Down
7 changes: 6 additions & 1 deletion compiler/rustc_parse/src/parser/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,12 @@ impl<'a> Parser<'a> {
if !self.maybe_consume_incorrect_semicolon(&items) {
let msg = &format!("expected item, found {token_str}");
let mut err = self.struct_span_err(self.token.span, msg);
err.span_label(self.token.span, "expected item");
let label = if self.is_kw_followed_by_ident(kw::Let) {
"consider using `const` or `static` instead of `let` for global variables"
} else {
"expected item"
};
err.span_label(self.token.span, label);
return Err(err);
}
}
Expand Down
156 changes: 77 additions & 79 deletions compiler/rustc_typeck/src/astconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ use rustc_trait_selection::traits::error_reporting::{
};
use rustc_trait_selection::traits::wf::object_region_bounds;

use smallvec::SmallVec;
use smallvec::{smallvec, SmallVec};
use std::collections::BTreeSet;
use std::slice;

Expand Down Expand Up @@ -368,36 +368,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
return (tcx.intern_substs(&[]), arg_count);
}

let is_object = self_ty.map_or(false, |ty| ty == self.tcx().types.trait_object_dummy_self);

struct SubstsForAstPathCtxt<'a, 'tcx> {
astconv: &'a (dyn AstConv<'tcx> + 'a),
def_id: DefId,
generic_args: &'a GenericArgs<'a>,
span: Span,
missing_type_params: Vec<Symbol>,
inferred_params: Vec<Span>,
infer_args: bool,
is_object: bool,
}

impl<'tcx, 'a> SubstsForAstPathCtxt<'tcx, 'a> {
fn default_needs_object_self(&mut self, param: &ty::GenericParamDef) -> bool {
let tcx = self.astconv.tcx();
if let GenericParamDefKind::Type { has_default, .. } = param.kind {
if self.is_object && has_default {
let default_ty = tcx.at(self.span).type_of(param.def_id);
let self_param = tcx.types.self_param;
if default_ty.walk().any(|arg| arg == self_param.into()) {
// There is no suitable inference default for a type parameter
// that references self, in an object type.
return true;
}
}
}

false
}
}

impl<'a, 'tcx> CreateSubstsForGenericArgsCtxt<'a, 'tcx> for SubstsForAstPathCtxt<'a, 'tcx> {
Expand Down Expand Up @@ -500,41 +477,23 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
GenericParamDefKind::Type { has_default, .. } => {
if !infer_args && has_default {
// No type parameter provided, but a default exists.

// If we are converting an object type, then the
// `Self` parameter is unknown. However, some of the
// other type parameters may reference `Self` in their
// defaults. This will lead to an ICE if we are not
// careful!
if self.default_needs_object_self(param) {
self.missing_type_params.push(param.name);
tcx.ty_error().into()
} else {
// This is a default type parameter.
let substs = substs.unwrap();
if substs.iter().any(|arg| match arg.unpack() {
GenericArgKind::Type(ty) => ty.references_error(),
_ => false,
}) {
// Avoid ICE #86756 when type error recovery goes awry.
return tcx.ty_error().into();
}
self.astconv
.normalize_ty(
self.span,
EarlyBinder(tcx.at(self.span).type_of(param.def_id))
.subst(tcx, substs),
)
.into()
let substs = substs.unwrap();
if substs.iter().any(|arg| match arg.unpack() {
GenericArgKind::Type(ty) => ty.references_error(),
_ => false,
}) {
// Avoid ICE #86756 when type error recovery goes awry.
return tcx.ty_error().into();
}
self.astconv
.normalize_ty(
self.span,
EarlyBinder(tcx.at(self.span).type_of(param.def_id))
.subst(tcx, substs),
)
.into()
} else if infer_args {
// No type parameters were provided, we can infer all.
let param = if !self.default_needs_object_self(param) {
Some(param)
} else {
None
};
self.astconv.ty_infer(param, self.span).into()
self.astconv.ty_infer(Some(param), self.span).into()
} else {
// We've already errored above about the mismatch.
tcx.ty_error().into()
Expand Down Expand Up @@ -564,10 +523,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
def_id,
span,
generic_args,
missing_type_params: vec![],
inferred_params: vec![],
infer_args,
is_object,
};
let substs = Self::create_substs_for_generic_args(
tcx,
Expand All @@ -579,13 +536,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&mut substs_ctx,
);

self.complain_about_missing_type_params(
substs_ctx.missing_type_params,
def_id,
span,
generic_args.args.is_empty(),
);

debug!(
"create_substs_for_ast_path(generic_params={:?}, self_ty={:?}) -> {:?}",
generics, self_ty, substs
Expand Down Expand Up @@ -1490,23 +1440,71 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// Erase the `dummy_self` (`trait_object_dummy_self`) used above.
let existential_trait_refs = regular_traits.iter().map(|i| {
i.trait_ref().map_bound(|trait_ref: ty::TraitRef<'tcx>| {
if trait_ref.self_ty() != dummy_self {
// FIXME: There appears to be a missing filter on top of `expand_trait_aliases`,
// which picks up non-supertraits where clauses - but also, the object safety
// completely ignores trait aliases, which could be object safety hazards. We
// `delay_span_bug` here to avoid an ICE in stable even when the feature is
// disabled. (#66420)
tcx.sess.delay_span_bug(
DUMMY_SP,
&format!(
"trait_ref_to_existential called on {:?} with non-dummy Self",
trait_ref,
),
assert_eq!(trait_ref.self_ty(), dummy_self);

// Verify that `dummy_self` did not leak inside default type parameters. This
// could not be done at path creation, since we need to see through trait aliases.
let mut missing_type_params = vec![];
let mut references_self = false;
let generics = tcx.generics_of(trait_ref.def_id);
let substs: Vec<_> = trait_ref
.substs
.iter()
.enumerate()
.skip(1) // Remove `Self` for `ExistentialPredicate`.
.map(|(index, arg)| {
if let ty::GenericArgKind::Type(ty) = arg.unpack() {
debug!(?ty);
if ty == dummy_self {
let param = &generics.params[index];
missing_type_params.push(param.name);
tcx.ty_error().into()
} else if ty.walk().any(|arg| arg == dummy_self.into()) {
references_self = true;
tcx.ty_error().into()
} else {
arg
}
} else {
arg
}
})
.collect();
let substs = tcx.intern_substs(&substs[..]);

let span = i.bottom().1;
let empty_generic_args = trait_bounds.iter().any(|hir_bound| {
hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id)
&& hir_bound.span.contains(span)
});
self.complain_about_missing_type_params(
missing_type_params,
trait_ref.def_id,
span,
empty_generic_args,
);

if references_self {
let def_id = i.bottom().0.def_id();
let mut err = struct_span_err!(
tcx.sess,
i.bottom().1,
E0038,
"the {} `{}` cannot be made into an object",
tcx.def_kind(def_id).descr(def_id),
tcx.item_name(def_id),
);
err.note(
rustc_middle::traits::ObjectSafetyViolation::SupertraitSelf(smallvec![])
.error_msg(),
);
err.emit();
}
ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)

ty::ExistentialTraitRef { def_id: trait_ref.def_id, substs }
})
});

let existential_projections = bounds.projection_bounds.iter().map(|(bound, _)| {
bound.map_bound(|b| {
if b.projection_ty.self_ty() != dummy_self {
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/alloc/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ use crate::ptr;
/// {
/// return null_mut();
/// };
/// (self.arena.get() as *mut u8).add(allocated)
/// self.arena.get().cast::<u8>().add(allocated)
/// }
/// unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
/// }
Expand Down
4 changes: 4 additions & 0 deletions library/core/src/fmt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ pub trait Write {
///
/// This function will return an instance of [`Error`] on error.
///
/// The purpose of std::fmt::Error is to abort the formatting operation when the underlying
/// destination encounters some error preventing it from accepting more text; it should
/// generally be propagated rather than handled, at least when implementing formatting traits.
///
/// # Examples
///
/// ```
Expand Down
17 changes: 9 additions & 8 deletions library/core/src/ptr/const_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1267,20 +1267,21 @@ impl<T: ?Sized> *const T {
/// Accessing adjacent `u8` as `u16`
///
/// ```
/// # fn foo(n: usize) {
/// # use std::mem::align_of;
/// use std::mem::align_of;
///
/// # unsafe {
/// let x = [5u8, 6u8, 7u8, 8u8, 9u8];
/// let ptr = x.as_ptr().add(n) as *const u8;
/// let x = [5_u8, 6, 7, 8, 9];
/// let ptr = x.as_ptr();
/// let offset = ptr.align_offset(align_of::<u16>());
/// if offset < x.len() - n - 1 {
/// let u16_ptr = ptr.add(offset) as *const u16;
/// assert_ne!(*u16_ptr, 500);
///
/// if offset < x.len() - 1 {
/// let u16_ptr = ptr.add(offset).cast::<u16>();
/// assert!(*u16_ptr == u16::from_ne_bytes([5, 6]) || *u16_ptr == u16::from_ne_bytes([6, 7]));
/// } else {
/// // while the pointer can be aligned via `offset`, it would point
/// // outside the allocation
/// }
/// # } }
/// # }
/// ```
#[stable(feature = "align_offset", since = "1.36.0")]
#[rustc_const_unstable(feature = "const_align_offset", issue = "90962")]
Expand Down
Loading