Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
28 changes: 28 additions & 0 deletions compiler/rustc_ast_lowering/src/delegation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ use hir::{BodyId, HirId};
use rustc_abi::ExternAbi;
use rustc_ast::*;
use rustc_errors::ErrorGuaranteed;
use rustc_hir::attrs::{AttributeKind, InlineAttr};
use rustc_hir::def_id::DefId;
use rustc_middle::span_bug;
use rustc_middle::ty::{Asyncness, ResolverAstLowering};
Expand Down Expand Up @@ -87,6 +88,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
let sig_id = self.get_delegation_sig_id(item_id, delegation.id, span, is_in_trait_impl);
match sig_id {
Ok(sig_id) => {
self.add_inline_attribute_if_needed(span);

let is_method = self.is_method(sig_id, span);
let (param_count, c_variadic) = self.param_count(sig_id);
let decl = self.lower_delegation_decl(sig_id, param_count, c_variadic, span);
Expand All @@ -100,6 +103,31 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}

fn add_inline_attribute_if_needed(&mut self, span: Span) {
const PARENT_ID: hir::ItemLocalId = hir::ItemLocalId::ZERO;
let create_inline_attr_slice =
|| [hir::Attribute::Parsed(AttributeKind::Inline(InlineAttr::Hint, span))];

let new_attributes = match self.attrs.get(&PARENT_ID) {
Some(attrs) => {
// Check if reuse already specifies any inline attribute, if so, do nothing
if attrs
.iter()
.any(|a| matches!(a, hir::Attribute::Parsed(AttributeKind::Inline(..))))
{
return;
}

self.arena.alloc_from_iter(
attrs.into_iter().map(|a| a.clone()).chain(create_inline_attr_slice()),
)
}
None => self.arena.alloc_from_iter(create_inline_attr_slice()),
};

self.attrs.insert(PARENT_ID, new_attributes);
}

fn get_delegation_sig_id(
&self,
item_id: NodeId,
Expand Down
94 changes: 94 additions & 0 deletions tests/pretty/delegation_inline_attribute.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
//@ pretty-compare-only
//@ pretty-mode:hir
//@ pp-exact:delegation_inline_attribute.pp

#![allow(incomplete_features)]
#![feature(fn_delegation)]
#[attr = MacroUse {arguments: UseAll}]
extern crate std;
#[prelude_import]
use ::std::prelude::rust_2015::*;

mod to_reuse {
fn foo(x: usize) -> usize { x }
}

// Check that #[inline(hint)] is added to foo reuse
#[attr = Inline(Hint)]
fn bar(arg0: _) -> _ { to_reuse::foo(self + 1) }

trait Trait {
fn foo(&self) { }
fn foo1(&self) { }
fn foo2(&self) { }
fn foo3(&self) { }
fn foo4(&self) { }
}

impl Trait for u8 { }

struct S(u8);

mod to_import {
fn check(arg: &'_ u8) -> &'_ u8 { arg }
}

impl Trait for S {
// Check that #[inline(hint)] is added to foo reuse
#[attr = Inline(Hint)]
fn foo(self: _)
->
_ {
{
// Check that #[inline(hint)] is added to foo0 reuse inside another reuse
#[attr = Inline(Hint)]
fn foo0(arg0: _) -> _ { to_reuse::foo(self + 1) }

// Check that #[inline(hint)] is added when other attributes present in inner reuse
#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
#[attr = MustUse]
#[attr = Cold]
#[attr = Inline(Hint)]
fn foo1(arg0: _) -> _ { to_reuse::foo(self / 2) }

// Check that #[inline(never)] is preserved in inner reuse
#[attr = Inline(Never)]
fn foo2(arg0: _) -> _ { to_reuse::foo(self / 2) }

// Check that #[inline(always)] is preserved in inner reuse
#[attr = Inline(Always)]
fn foo3(arg0: _) -> _ { to_reuse::foo(self / 2) }

// Check that #[inline(never)] is preserved when there are other attributes in inner reuse
#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
#[attr = Inline(Never)]
#[attr = MustUse]
#[attr = Cold]
fn foo4(arg0: _) -> _ { to_reuse::foo(self / 2) }
}.foo()
}

// Check that #[inline(hint)] is added when there are other attributes present in trait reuse
#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
#[attr = MustUse]
#[attr = Cold]
#[attr = Inline(Hint)]
fn foo1(self: _) -> _ { self.0.foo1() }

// Check that #[inline(never)] is preserved in trait reuse
#[attr = Inline(Never)]
fn foo2(self: _) -> _ { self.0.foo2() }

// Check that #[inline(always)] is preserved in trait reuse
#[attr = Inline(Always)]
fn foo3(self: _) -> _ { self.0.foo3() }

// Check that #[inline(never)] is preserved when there are other attributes in trait reuse
#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
#[attr = Inline(Never)]
#[attr = MustUse]
#[attr = Cold]
fn foo4(self: _) -> _ { self.0.foo4() }
}

fn main() { }
104 changes: 104 additions & 0 deletions tests/pretty/delegation_inline_attribute.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
//@ pretty-compare-only
//@ pretty-mode:hir
//@ pp-exact:delegation_inline_attribute.pp

#![allow(incomplete_features)]
#![feature(fn_delegation)]

mod to_reuse {
pub fn foo(x: usize) -> usize {
x
}
}

// Check that #[inline(hint)] is added to foo reuse
reuse to_reuse::foo as bar {
self + 1
}

trait Trait {
fn foo(&self) {}
fn foo1(&self) {}
fn foo2(&self) {}
fn foo3(&self) {}
fn foo4(&self) {}
}

impl Trait for u8 {}

struct S(u8);

mod to_import {
pub fn check(arg: &u8) -> &u8 { arg }
}

impl Trait for S {
// Check that #[inline(hint)] is added to foo reuse
reuse Trait::foo {
// Check that #[inline(hint)] is added to foo0 reuse inside another reuse
reuse to_reuse::foo as foo0 {
self + 1
}

// Check that #[inline(hint)] is added when other attributes present in inner reuse
#[cold]
#[must_use]
#[deprecated]
reuse to_reuse::foo as foo1 {
self / 2
}

// Check that #[inline(never)] is preserved in inner reuse
#[inline(never)]
reuse to_reuse::foo as foo2 {
self / 2
}

// Check that #[inline(always)] is preserved in inner reuse
#[inline(always)]
reuse to_reuse::foo as foo3 {
self / 2
}

// Check that #[inline(never)] is preserved when there are other attributes in inner reuse
#[cold]
#[must_use]
#[inline(never)]
#[deprecated]
reuse to_reuse::foo as foo4 {
self / 2
}
}

// Check that #[inline(hint)] is added when there are other attributes present in trait reuse
#[cold]
#[must_use]
#[deprecated]
reuse Trait::foo1 {
self.0
}

// Check that #[inline(never)] is preserved in trait reuse
#[inline(never)]
reuse Trait::foo2 {
self.0
}

// Check that #[inline(always)] is preserved in trait reuse
#[inline(always)]
reuse Trait::foo3 {
self.0
}

// Check that #[inline(never)] is preserved when there are other attributes in trait reuse
#[cold]
#[must_use]
#[inline(never)]
#[deprecated]
reuse Trait::foo4 {
self.0
}
}

fn main() {
}
2 changes: 2 additions & 0 deletions tests/pretty/hir-delegation.pp
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@
fn b<C>(e: C) { }

trait G {
#[attr = Inline(Hint)]
fn b(arg0: _) -> _ { b({ }) }
}

mod m {
fn add(a: u32, b: u32) -> u32 { a + b }
}

#[attr = Inline(Hint)]
fn add(arg0: _, arg1: _) -> _ { m::add(arg0, arg1) }

fn main() { { let _ = add(1, 2); }; }
Loading