Skip to content

Rollup of 4 pull requests #97356

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

Merged
merged 9 commits into from
May 24, 2022
8 changes: 4 additions & 4 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,12 +343,12 @@ pub struct GenericArgs<'hir> {
pub span_ext: Span,
}

impl GenericArgs<'_> {
impl<'hir> GenericArgs<'hir> {
pub const fn none() -> Self {
Self { args: &[], bindings: &[], parenthesized: false, span_ext: DUMMY_SP }
}

pub fn inputs(&self) -> &[Ty<'_>] {
pub fn inputs(&self) -> &[Ty<'hir>] {
if self.parenthesized {
for arg in self.args {
match arg {
Expand Down Expand Up @@ -549,7 +549,7 @@ impl<'hir> Generics<'hir> {
&NOPE
}

pub fn get_named(&self, name: Symbol) -> Option<&GenericParam<'_>> {
pub fn get_named(&self, name: Symbol) -> Option<&GenericParam<'hir>> {
for param in self.params {
if name == param.name.ident().name {
return Some(param);
Expand Down Expand Up @@ -608,7 +608,7 @@ impl<'hir> Generics<'hir> {
pub fn bounds_for_param(
&self,
param_def_id: LocalDefId,
) -> impl Iterator<Item = &WhereBoundPredicate<'_>> {
) -> impl Iterator<Item = &WhereBoundPredicate<'hir>> {
self.predicates.iter().filter_map(move |pred| match pred {
WherePredicate::BoundPredicate(bp) if bp.is_param_bound(param_def_id.to_def_id()) => {
Some(bp)
Expand Down
62 changes: 57 additions & 5 deletions compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2010,6 +2010,12 @@ impl<'a> Parser<'a> {
Ok(self.mk_expr(blk.span, ExprKind::Block(blk, opt_label), attrs))
}

/// Parse a block which takes no attributes and has no label
fn parse_simple_block(&mut self) -> PResult<'a, P<Expr>> {
let blk = self.parse_block()?;
Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new()))
}

/// Recover on an explicitly quantified closure expression, e.g., `for<'a> |x: &'a u8| *x + 1`.
fn recover_quantified_closure_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
let lo = self.token.span;
Expand Down Expand Up @@ -2157,14 +2163,22 @@ impl<'a> Parser<'a> {
let lo = self.prev_token.span;
let cond = self.parse_cond_expr()?;

self.parse_if_after_cond(attrs, lo, cond)
}

fn parse_if_after_cond(
&mut self,
attrs: AttrVec,
lo: Span,
cond: P<Expr>,
) -> PResult<'a, P<Expr>> {
let missing_then_block_binop_span = || {
match cond.kind {
ExprKind::Binary(Spanned { span: binop_span, .. }, _, ref right)
if let ExprKind::Block(..) = right.kind => Some(binop_span),
_ => None
}
};

// Verify that the parsed `if` condition makes sense as a condition. If it is a block, then
// verify that the last statement is either an implicit return (no `;`) or an explicit
// return. This won't catch blocks with an explicit `return`, but that would be caught by
Expand Down Expand Up @@ -2256,15 +2270,53 @@ impl<'a> Parser<'a> {

/// Parses an `else { ... }` expression (`else` token already eaten).
fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
let ctx_span = self.prev_token.span; // `else`
let else_span = self.prev_token.span; // `else`
let attrs = self.parse_outer_attributes()?.take_for_recovery(); // For recovery.
let expr = if self.eat_keyword(kw::If) {
self.parse_if_expr(AttrVec::new())?
} else if self.check(&TokenKind::OpenDelim(Delimiter::Brace)) {
self.parse_simple_block()?
} else {
let blk = self.parse_block()?;
self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new())
let snapshot = self.create_snapshot_for_diagnostic();
let first_tok = super::token_descr(&self.token);
let first_tok_span = self.token.span;
match self.parse_expr() {
Ok(cond)
// If it's not a free-standing expression, and is followed by a block,
// then it's very likely the condition to an `else if`.
if self.check(&TokenKind::OpenDelim(Delimiter::Brace))
&& classify::expr_requires_semi_to_be_stmt(&cond) =>
{
self.struct_span_err(first_tok_span, format!("expected `{{`, found {first_tok}"))
.span_label(else_span, "expected an `if` or a block after this `else`")
.span_suggestion(
cond.span.shrink_to_lo(),
"add an `if` if this is the condition to an chained `if` statement after the `else`",
"if ".to_string(),
Applicability::MaybeIncorrect,
).multipart_suggestion(
"... otherwise, place this expression inside of a block if it is not an `if` condition",
vec![
(cond.span.shrink_to_lo(), "{ ".to_string()),
(cond.span.shrink_to_hi(), " }".to_string()),
],
Applicability::MaybeIncorrect,
)
.emit();
self.parse_if_after_cond(AttrVec::new(), cond.span.shrink_to_lo(), cond)?
}
Err(e) => {
e.cancel();
self.restore_snapshot(snapshot);
self.parse_simple_block()?
},
Ok(_) => {
self.restore_snapshot(snapshot);
self.parse_simple_block()?
},
}
};
self.error_on_if_block_attrs(ctx_span, true, expr.span, &attrs);
self.error_on_if_block_attrs(else_span, true, expr.span, &attrs);
Ok(expr)
}

Expand Down
8 changes: 2 additions & 6 deletions library/core/src/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1390,16 +1390,14 @@ impl<'b, T: ?Sized> Ref<'b, T> {
/// # Examples
///
/// ```
/// #![feature(cell_filter_map)]
///
/// use std::cell::{RefCell, Ref};
///
/// let c = RefCell::new(vec![1, 2, 3]);
/// let b1: Ref<Vec<u32>> = c.borrow();
/// let b2: Result<Ref<u32>, _> = Ref::filter_map(b1, |v| v.get(1));
/// assert_eq!(*b2.unwrap(), 2);
/// ```
#[unstable(feature = "cell_filter_map", reason = "recently added", issue = "81061")]
#[stable(feature = "cell_filter_map", since = "1.63.0")]
#[inline]
pub fn filter_map<U: ?Sized, F>(orig: Ref<'b, T>, f: F) -> Result<Ref<'b, U>, Self>
where
Expand Down Expand Up @@ -1538,8 +1536,6 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
/// # Examples
///
/// ```
/// #![feature(cell_filter_map)]
///
/// use std::cell::{RefCell, RefMut};
///
/// let c = RefCell::new(vec![1, 2, 3]);
Expand All @@ -1555,7 +1551,7 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
///
/// assert_eq!(*c.borrow(), vec![1, 4, 3]);
/// ```
#[unstable(feature = "cell_filter_map", reason = "recently added", issue = "81061")]
#[stable(feature = "cell_filter_map", since = "1.63.0")]
#[inline]
pub fn filter_map<U: ?Sized, F>(mut orig: RefMut<'b, T>, f: F) -> Result<RefMut<'b, U>, Self>
where
Expand Down
3 changes: 3 additions & 0 deletions library/core/src/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -930,6 +930,9 @@ extern "rust-intrinsic" {
/// fn foo() -> i32 {
/// 0
/// }
/// // Crucially, we `as`-cast to a raw pointer before `transmute`ing to a function pointer.
/// // This avoids an integer-to-pointer `transmute`, which can be problematic.
/// // Transmuting between raw pointers and function pointers (i.e., two pointer types) is fine.
/// let pointer = foo as *const ();
/// let function = unsafe {
/// std::mem::transmute::<*const (), fn() -> i32>(pointer)
Expand Down
26 changes: 26 additions & 0 deletions library/core/src/primitive_docs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1351,6 +1351,32 @@ mod prim_ref {}
/// is a reference to the function-specific ZST. `&bar` is basically never what you
/// want when `bar` is a function.
///
/// ### Casting to and from integers
///
/// You cast function pointers directly to integers:
///
/// ```rust
/// let fnptr: fn(i32) -> i32 = |x| x+2;
/// let fnptr_addr = fnptr as usize;
/// ```
///
/// However, a direct cast back is not possible. You need to use `transmute`:
///
/// ```rust
/// # let fnptr: fn(i32) -> i32 = |x| x+2;
/// # let fnptr_addr = fnptr as usize;
/// let fnptr = fnptr_addr as *const ();
/// let fnptr: fn(i32) -> i32 = unsafe { std::mem::transmute(fnptr) };
/// assert_eq!(fnptr(40), 42);
/// ```
///
/// Crucially, we `as`-cast to a raw pointer before `transmute`ing to a function pointer.
/// This avoids an integer-to-pointer `transmute`, which can be problematic.
/// Transmuting between raw pointers and function pointers (i.e., two pointer types) is fine.
///
/// Note that all of this is not portable to platforms where function pointers and data pointers
/// have different sizes.
///
/// ### Traits
///
/// Function pointers implement the following traits:
Expand Down
26 changes: 26 additions & 0 deletions library/std/src/primitive_docs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1351,6 +1351,32 @@ mod prim_ref {}
/// is a reference to the function-specific ZST. `&bar` is basically never what you
/// want when `bar` is a function.
///
/// ### Casting to and from integers
///
/// You cast function pointers directly to integers:
///
/// ```rust
/// let fnptr: fn(i32) -> i32 = |x| x+2;
/// let fnptr_addr = fnptr as usize;
/// ```
///
/// However, a direct cast back is not possible. You need to use `transmute`:
///
/// ```rust
/// # let fnptr: fn(i32) -> i32 = |x| x+2;
/// # let fnptr_addr = fnptr as usize;
/// let fnptr = fnptr_addr as *const ();
/// let fnptr: fn(i32) -> i32 = unsafe { std::mem::transmute(fnptr) };
/// assert_eq!(fnptr(40), 42);
/// ```
///
/// Crucially, we `as`-cast to a raw pointer before `transmute`ing to a function pointer.
/// This avoids an integer-to-pointer `transmute`, which can be problematic.
/// Transmuting between raw pointers and function pointers (i.e., two pointer types) is fine.
///
/// Note that all of this is not portable to platforms where function pointers and data pointers
/// have different sizes.
///
/// ### Traits
///
/// Function pointers implement the following traits:
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/clean/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean
}
}

fn build_external_function(cx: &mut DocContext<'_>, did: DefId) -> clean::Function {
fn build_external_function<'tcx>(cx: &mut DocContext<'tcx>, did: DefId) -> clean::Function {
let sig = cx.tcx.fn_sig(did);

let predicates = cx.tcx.predicates_of(did);
Expand Down
Loading