안정성 속성
이 절에서는 rustc 표준 라이브러리에서 안정 API가 내부적으로 불안정 API를 사용할 수 있게 해 주는 안정성 속성과 체계를 설명합니다.
참고: 이 절은 언어 기능이 아니라 라이브러리 기능을 다룹니다. 언어 기능을 안정화하는 방법은 기능 안정화하기를 참고하십시오.
unstable
#[unstable(feature = "foo", issue = "1234", reason = "lorem ipsum")] 속성은 항목을 불안정한 것으로 명시적으로 표시합니다. “unstable“로 표시된 항목은 nightly 컴파일러에서도 크레이트에 해당하는 #![feature] 속성이 없으면 사용할 수 없습니다. 이 제한은 크레이트 경계를 넘을 때만 적용되므로, 불안정 항목을 정의한 크레이트 안에서는 해당 항목을 사용할 수 있습니다.
issue 필드는 관련된 GitHub 이슈 번호를 지정합니다. 이 필드는 필수이며, 모든 불안정 기능에는 관련된 추적 이슈가 있어야 합니다. 적절한 값이 없는 드문 경우에는 issue = "none"을 사용합니다.
unstable 속성은 모든 하위 항목에 전파되므로 하위 항목에 속성을 다시 적용할 필요가 없습니다. 따라서 이 속성을 모듈에 적용하면 모듈 안의 모든 항목이 불안정해집니다.
기능의 이름을 바꾸는 경우 old_name = "old_name"을 추가하면 유용한 오류 메시지를 표시할 수 있습니다.
특정 하위 항목에 #[stable] 속성을 사용하면 해당 항목을 안정 상태로 만들 수 있습니다. 안정성 체계는 pub가 동작하는 방식과 비슷하게 동작합니다. 공개되지 않은 모듈에 공개 함수가 있을 수 있듯이, 불안정 모듈에 안정 함수가 있을 수도 있고 그 반대도 가능합니다.
이전에는 rustc 버그 때문에 불안정 모듈 안의 안정 항목을 해당 위치에서 안정 코드가 사용할 수 있었습니다. 2024년 9월 기준으로, 실수로 안정화된 경로를 가진 항목에는 해당 경로에 의존하는 코드가 깨지지 않도록 #[rustc_allowed_through_unstable_modules] 속성이 지정되어 있습니다. 호환성을 깨는 변경을 피하는 데 필요한 경우가 아니라면 이 속성을 다른 항목에 추가하지 마십시오.
unstable 속성에는 soft 값을 지정할 수도 있으며, 이 값을 지정하면 하드 오류 대신 향후 호환되지 않는 기본 거부(deny-by-default) 린트가 됩니다. 이 값은 과거에 실수로 허용되었던 bench 속성에서 사용합니다. 이렇게 하면 Cargo의 린트 상한(lint capping)을 활용하여 의존성이 깨지는 것을 막을 수 있습니다.
stable
#[stable(feature = "foo", since = "1.420.69")] 속성은 항목을 안정화된 것으로 명시적으로 표시합니다. 안정 함수의 본문에서도 불안정한 요소를 사용할 수 있다는 점에 유의하십시오.
rustc_const_unstable
#[rustc_const_unstable(feature = "foo", issue = "1234", reason = "lorem ipsum")]는 unstable 속성과 동일한 인터페이스를 가집니다. 이 속성은 const fn의 const성(constness)이 불안정하다는 것을 표시하는 데 사용합니다. 이 속성은 다음과 같은 드문 경우에만 필요합니다:
const fn이 불안정 언어 기능이나 내장 함수(intrinsic)를 사용하는 경우입니다. (이런 경우에는 컴파일러가 속성을 추가하라고 알려 줍니다.)const fn이#[stable]이지만 아직 const-stable로 만들 의도가 없는 경우입니다.- const-unstable 내장 함수를 호출하는 데 필요한 기능 게이트를 변경하기 위한 것입니다.
const 안정성은 재귀적이라는 점에서 일반적인 안정성과 다릅니다. 즉, #[rustc_const_unstable(...)] 함수는 안정 코드에서 간접적으로도 호출할 수 없습니다. 이는 불안정한 컴파일러 구현 산출물이 실수로 안정 코드에 유출되거나, 불완전한 구현의 우발적인 특이점에 우리가 묶이게 되는 것을 방지하기 위함입니다. 이 검사를 세밀하게 조정하는 방법은 아래의 rustc_const_stable_indirect 및 rustc_allow_const_fn_unstable 속성을 참조하십시오.
rustc_const_stable
#[rustc_const_stable(feature = "foo", since = "1.420.69")] 속성은 const fn의 const성이 stable임을 명시적으로 표시합니다.
rustc_const_stable_indirect
#[rustc_const_stable_indirect] 속성을 #[rustc_const_unstable(...)] 함수에 추가하면 해당 함수를 #[rustc_const_stable(...)] 함수에서 호출할 수 있게 됩니다. 이는 해당 함수가 구현 측면에서 안정화될 준비가 되었음(즉, 불안정한 컴파일러 기능을 사용하지 않음)을 나타내며, 아직 const-stable이 아닌 유일한 이유는 API에 관한 우려 때문입니다.
이는 컴파일러에서 const 호출이 합성되는 언어 항목에도 추가해야 하며, 이를 통해 해당 호출이 재귀적 const 안정성 규칙을 우회하지 않도록 보장합니다.
rustc_intrinsic_const_stable_indirect
내장 함수에 이 속성을 지정하면 해당 내장 함수가 “공개 안정 함수에서 사용할 준비가 됨“으로 표시됩니다. 내장 함수에 rustc_const_unstable 속성이 있다면 제거해야 합니다. 내장 함수에 이 속성을 추가하려면 t-lang 및 wg-const-eval의 승인이 필요합니다!
rustc_default_body_unstable
#[rustc_default_body_unstable(feature = "foo", issue = "1234", reason = "lorem ipsum")] 속성은 unstable 속성과 동일한 인터페이스를 가집니다. 이 속성은 트레이트 내 항목의 기본 구현을 불안정으로 표시하는 데 사용됩니다. default-body-unstable 항목이 있는 트레이트는 그러한 항목마다 명시적인 본문을 제공하여 안정적으로 구현할 수 있으며, 또는 해당하는 #![feature]를 활성화하여 기본 본문을 사용할 수도 있습니다.
라이브러리 기능 안정화하기
기능을 안정화하려면 다음 단계를 따르십시오.
- @T-libs 멤버에게 추적 이슈에서 FCP를 시작해 달라고 요청하고, FCP가 (
disposition-merge로) 완료될 때까지 기다리십시오. #[unstable(...)]을#[stable(since = "CURRENT_RUSTC_VERSION")]로 변경하십시오.- 이 API에 대한 모든 테스트 또는 문서 테스트에서
#![feature(...)]를 제거하십시오. 해당 기능이 컴파일러나 도구에서 사용되고 있다면 그곳에서도 제거하십시오. const fn인 경우#[rustc_const_stable(since = "CURRENT_RUSTC_VERSION")]를 추가하십시오. 또는 아직 const 안정화할 대상이 아니라면, 새로운 기능 게이트(와 새 추적 이슈)에 대해#[rustc_const_unstable(...)]를 추가하십시오.rust-lang/rust를 대상으로 PR을 여십시오.- 적절한 레이블을 추가하십시오:
@rustbot modify labels: +T-libs. - 추적 이슈에 링크하고 “Closes #XXXXX“라고 적으십시오.
- 적절한 레이블을 추가하십시오:
기능 안정화의 예시는 FCP가 진행된 추적 이슈 #81656과 관련 구현 PR #84642에서 확인할 수 있습니다.
allow_internal_unstable
매크로와 컴파일러 디슈가링(desugaring)은 자신의 본문을 호출 지점에 노출합니다. 표준 라이브러리의 매크로에서 불안정한 기능을 사용할 수 없는 제약을 우회하기 위해, 지정한 기능을 안정 매크로에서 사용할 수 있게 해 주는 #[allow_internal_unstable(feature1, feature2)] 속성이 있습니다.
매크로가 const 컨텍스트에서 사용되어 #[rustc_const_unstable(...)] 함수에 대한 호출을 생성하는 경우, allow_internal_unstable이 있더라도 여전히 거부된다는 점에 유의하십시오. 매크로가 재귀적 const 안정성 검사를 실수로 우회하지 못하도록 해당 함수에 #[rustc_const_stable_indirect]를 추가하십시오.
rustc_allow_const_fn_unstable
위에서 설명한 것처럼, 안정 const fn 내부에서는 불안정한 const 기능을 간접적으로도 사용할 수 없습니다.
그러나 때로는 어떤 기능이 언제 안정화될지는 모르더라도 안정화될 것임은 확실히 알고 있거나, 안정적인(그러나 예를 들어 런타임에 느린) 우회 방법이 존재하여, 불안정 기능을 폐기하더라도 언제든 어떤 안정 버전으로 대체할 수 있는 경우가 있습니다. 그러한 경우, [rustc_allow_const_fn_unstable(feature1, feature2)] 속성을 사용하여 안정(또는 간접적으로 안정) const fn의 본문에서 일부 불안정 기능을 허용할 수 있습니다.
또한 런타임에 호출하든 컴파일 타임에 호출하든 동일하게 동작해야 한다는 const fn 불변 조건을 지키도록 주의해야 합니다(이 블로그 글도 참고하십시오). 이는 예를 들어 메모리 주소를 정수로 transmute하는 const fn을 만들어서는 안 된다는 의미입니다. 대상의 주소는 비결정적이며 컴파일 타임에는 알 수 없는 경우가 많기 때문입니다.
어떤 const fn에든 rustc_allow_const_fn_unstable 속성을 추가하는 경우에는 항상 @rust-lang/wg-const-eval에 알리십시오.
staged_api
stable 또는 unstable 속성을 사용하는 모든 크레이트는 크레이트에 #![feature(staged_api)] 속성을 포함해야 합니다.
deprecated
표준 라이브러리의 사용 중단(deprecation)은 사용자 코드의 사용 중단과 거의 동일합니다. 항목에 #[deprecated]가 사용되는 경우, 해당 항목에는 stable 또는 unstable 속성도 있어야 합니다.
deprecated는 다음과 같은 형식을 가집니다.
#[deprecated(
since = "1.38.0",
note = "explanation for deprecation",
suggestion = "other_function"
)]
suggestion 필드는 선택 사항입니다. 지정하는 경우, 경고를 수정하기 위해 기계적으로 적용할 수 있는 제안으로 사용할 수 있는 문자열이어야 합니다. 이는 일반적으로 식별자의 이름이 바뀌었지만 그 외에 중요한 변경이 필요하지 않은 경우에 사용됩니다. suggestion 필드를 사용하는 경우, 크레이트 루트에 #![feature(deprecated_suggestion)]가 있어야 합니다.
사용자 코드와의 또 다른 차이점은 since 필드가 실제로 현재 rustc 버전과 비교하여 검사된다는 것입니다. since가 미래 버전인 경우 deprecated_in_future 린트가 발생하는데, 이 린트의 기본값은 allow이지만 표준 라이브러리의 대부분은 #![warn(deprecated_in_future)]로 이를 경고로 격상합니다.
unstable_feature_bound
#[unstable_feature_bound(foo)] 속성을 #[unstable] 속성과 함께 사용하면 안정 타입과 안정 트레이트의 impl을 불안정으로 표시할 수 있습니다. std/core에서 #[unstable_feature_bound(foo)]가 지정된 항목은 마찬가지로 #[unstable_feature_bound(foo)]가 지정된 다른 항목에서만 사용할 수 있습니다. std/core 외부에서 #[unstable_feature_bound(foo)]가 있는 항목을 사용하려면 크레이트에 #![feature(foo)] 속성으로 해당 기능을 활성화해야 합니다.
현재 #[unstable_feature_bound]를 지정할 수 있는 항목은 다음과 같습니다.
impl- 자유 함수
- 트레이트
이름이 바뀌거나 제거된 기능
불안정 기능은 이름이 바뀌거나 제거될 수 있습니다. 기능의 이름을 바꾸는 경우 #[unstable] 속성에 old_name = "old_name"을 추가할 수 있습니다. 기능을 제거하는 경우, 제거된 기능을 사용하는 사용자에게 적절한 오류 메시지를 표시하려면 #![unstable_removed(feature = "foo", reason = "brief description", link = "link", since = "1.90.0")] 속성을 사용해야 합니다.
link 필드를 사용하면 GitHub 이슈, 댓글, PR처럼 기능 제거와 가장 관련 깊은 정보로 연결되는 링크를 걸 수 있습니다.